Bottom button bar overlaps the last element of Lis

2019-05-28 19:09发布

问题:

I have a listview which is part of an Activity. I want user to have a choice for batch deleting the items in the listview, so when he chooses the corresponding option from the menu, every list item gets a checkbox next to it. When user clicks any checkbox, a button bar is to slide up from bottom (as in gmail app) and clicking delete button deletes the selected items, however clicking cancel button on the bar would uncheck all the checked items.

This is my page layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"    
    android:background="@android:color/transparent"
    >

    <FrameLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
    >

    <LinearLayout
      android:id="@+id/list_area"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      android:layout_weight="1"  
      >
      <ListView
          android:id="@+id/mylist"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:background="@android:color/transparent" 
          android:drawSelectorOnTop="false"
          android:layout_weight="1"
      />

      <TextView
        android:id="@+id/empty_list_message"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textColor="#FFFFFF"
        android:layout_gravity="center_vertical|center_horizontal"
        android:text="@string/msg_for_emptyschd"
        android:layout_margin="14dip"
        android:layout_weight="1"
         />
  </LinearLayout>

  <RelativeLayout
    android:id="@+id/bottom_action_bar"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/schedule_bottom_actionbar_border"
    android:layout_marginBottom="2dip"
    android:layout_gravity="bottom"
    android:visibility="gone"
    >    
    <Button
        android:id="@+id/delete_selecteditems_button"
        android:text="Deleted Selected"
        android:layout_width="140dip"
        android:layout_height="40dip"
        android:layout_alignParentLeft="true"
        android:layout_marginLeft="3dip"
        android:layout_marginTop="3dip"
    />

    <Button
    android:id="@+id/cancel_button"
        android:text="Cancel"
        android:layout_width="140dip"
        android:layout_height="40dip"
        android:layout_alignParentRight="true"
        android:layout_marginRight="3dip"
        android:layout_marginTop="3dip"
    />    
     </RelativeLayout>    
   </FrameLayout>        
</LinearLayout>

so far, I have got everything working except that when the bottom bar becomes visible upon checkbox selection, it overlaps the last element of the list. All other list items can be scrolled up, but you cant scroll up the very last item of the list, therefore user can not select that item if he intends to. Here is the screenshot of the overlap.

I have tried using the listview footer option, but that appends the bar to the end of the list instead of keeping it fixed at the bottom of the screen. Is there a way I could "raise" the listview enough so that the overlap wont happen?? BTW, I have already tried adding the bottom-margin to the listview itself, or the LinearLayout wrapping the listview right before making the button-bar visible, but it introduces other bugs like clicking one checkbox checks some another checkbox in listview.

回答1:

Didn't test this, but i am pretty sure it is the FrameLayout that is causing this :). Because FrameLayout does not care about the "weight" you gave it. FrameLayout just places the views you insert in front of each other. And the second one you gave, you said android:layout_gravity="bottom" which makes it align at the bottom. but just infront of the listview. Remove FrameLayout and it should work i think.

Try it like this:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="fill_parent"
    android:layout_height="fill_parent" android:background="@android:color/transparent">

    <LinearLayout android:id="@+id/list_area"
        android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1">
        <ListView android:id="@+id/mylist" android:layout_width="fill_parent"
            android:layout_height="wrap_content" android:background="@android:color/transparent"
            android:drawSelectorOnTop="false" android:layout_weight="1" />

        <TextView android:id="@+id/empty_list_message"
            android:layout_width="fill_parent" android:layout_height="wrap_content"
            android:textColor="#FFFFFF" android:layout_gravity="center_vertical|center_horizontal"
            android:text="@string/msg_for_emptyschd" android:layout_margin="14dip"
            android:layout_weight="1" />
    </LinearLayout>

    <RelativeLayout android:id="@+id/bottom_action_bar"
        android:orientation="horizontal" android:layout_width="fill_parent"
        android:layout_height="wrap_content" android:background="@drawable/schedule_bottom_actionbar_border"
        android:layout_marginBottom="2dip"
        android:visibility="gone">
        <Button android:id="@+id/delete_selecteditems_button"
            android:text="Deleted Selected" android:layout_width="140dip"
            android:layout_height="40dip" android:layout_alignParentLeft="true"
            android:layout_marginLeft="3dip" android:layout_marginTop="3dip" />
        <Button android:id="@+id/cancel_button" android:text="Cancel"
            android:layout_width="140dip" android:layout_height="40dip"
            android:layout_alignParentRight="true" android:layout_marginRight="3dip"
            android:layout_marginTop="3dip" />
    </RelativeLayout>

</LinearLayout>


回答2:

Seems like I have solved the problem of strange checkbox behavior. First, the problem was happening because as soon as the listview gets resized, it redraws itself, therefore getView() gets called again for all the visible list items. Since I am using a ViewHolder, and the view is getting reused, it seems like it causes the same checkbox to get reused again for some other list item. So therefore, when I was clicking one checkbox, some other checkbox was getting clicked instead. Since, this call to refresh the listview was only happening when the list was being resized, and list was getting resized only on marking a checkbox in list when no other checkbox was marked, this problem does not appear again after the first checkbox has been marked.

I solved the problem by creating a custom collection class to store the checked items, and before putting the item in this collection, I clone the clicked checkbox's tag and clicklistener over into a new checkbox and store that new checkbox now into the collection. This solved the strange behavior of checkboxes. This may not be the best solution to the problem, so if you know anything better than this, please share.