解决 Android 中使用ListView和CheckBox批量操作时若干问题

本文可以帮助 完美解决 在Android中使用ListView时批量操作CheckBox出现的各种问题。

在Android中使用ListActivity可以很方便的绑定一组数据或者一个查询。但是,使用过程中也会遇到一些问题。在此,我将自己遇到的问题以及解决方法记录下来,一方面做一个备忘,同时,也希望有缘人能少走弯路。

问题一: Listview中的Item数目到底是多少

ListView中的Item数目可以使用getCount方法获得,经过验证得到的结果是,其Item数目等于界面上显示的Item数目,这个数目可能小于实际上绑定的数据条目数。

那么,在实际中如果有额外的非绑定数据源的数据需要编辑保存的时候,如何才能保存他们呢?

解决该问题的方法是:自定义ListAdapter,在其中保存额外需要保存的数据。

问题二:在Item中添加CheckBox出现麻烦了

在item中添加Checkbox的时候不小心会遇到麻烦,可能出现的情况是:

(1)Listview不能相应点击事件

(2)Listview点击第一个Item的时候最后一个Item也出现点击事件(反之亦然)

以上两种情况是我实际遇到的bug,经过各种纠结和反复测试,出现问题的原因是CheckBox相应焦点、点击事件的优先级别比Listview要高,所以出现问题。

解决方法如下(和问题一一对应):

(1)将Checkbox设置focusable属性为false

(2)接着将CheckBox设置Clickable属性为false.

以下是本人程序片段,仅供参考:

  1.   
  2. xml version="1.0" encoding="utf-8"?>  
  3. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     android:paddingLeft="8dp"  
  7.     android:paddingRight="8dp" >  
  8.   
  9.     <TextView  
  10.         android:id="@+id/ans_title"  
  11.         android:layout_width="fill_parent"  
  12.         android:layout_height="wrap_content"  
  13.         android:layout_alignParentTop="true"  
  14.         android:gravity="center"  
  15.         android:textSize="15sp"  
  16.         android:textStyle="bold" />  
  17.   
  18.     <RelativeLayout  
  19.         android:id="@+id/ans_foot"  
  20.         android:layout_width="fill_parent"  
  21.         android:layout_height="wrap_content"  
  22.         android:layout_alignParentBottom="true"  
  23.         android:paddingLeft="8sp"  
  24.         android:paddingRight="8sp" >  
  25.   
  26.         <CheckBox  
  27.             android:id="@+id/ans_cbx_select"  
  28.             android:layout_width="wrap_content"  
  29.             android:layout_height="wrap_content"  
  30.             android:layout_alignParentRight="true"  
  31.             android:layout_marginLeft="10sp"  
  32.             android:checked="false" />  
  33.         <Button  
  34.             android:id="@+id/ans_btn_showInMap"  
  35.             android:layout_width="fill_parent"  
  36.             android:layout_height="wrap_content"  
  37.             android:layout_toLeftOf="@id/ans_cbx_select"  
  38.             android:text="@string/ans_btn_showInMap" />  
  39.     RelativeLayout>  
  40.   
  41.     <ListView  
  42.         android:id="@android:id/list"  
  43.         android:layout_width="fill_parent"  
  44.         android:layout_height="fill_parent"  
  45.         android:layout_above="@id/ans_foot"  
  46.         android:layout_below="@id/ans_title"  
  47.         android:drawSelectorOnTop="false" >  
  48.     ListView>  
  49.   
  50.     <TextView  
  51.         android:id="@android:id/empty"  
  52.         android:layout_width="fill_parent"  
  53.         android:layout_height="fill_parent"  
  54.         android:gravity="center"  
  55.         android:text="@string/ans_list_empty"  
  56.         android:textSize="25sp"  
  57.         android:textStyle="bold" >  
  58.     TextView>  
  59.   
  60. RelativeLayout>  
    1.   
    2. xml version="1.0" encoding="utf-8"?>  
    3. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    4.     android:layout_width="fill_parent"  
    5.     android:layout_height="wrap_content"  
    6.     android:padding="10sp" >  
    7.   
    8.     <CheckBox  
    9.         android:id="@+id/ans_item_select"  
    10.         android:layout_width="wrap_content"  
    11.         android:layout_height="wrap_content"  
    12.         android:layout_alignParentRight="true"  
    13.   
    14.         android:focusable="false"  
    15.         android:clickable="false"  
    16.   
    17.         android:checked="false"  
    18.         android:gravity="center_vertical" />  
    19.   
    20.     <RelativeLayout  
    21.         android:layout_width="fill_parent"  
    22.         android:layout_height="wrap_content"  
    23.         android:layout_alignParentLeft="true"  
    24.         >  
    25.   
    26.         ....  
    27.   
    28.         <TextView  
    29.             android:id="@+id/ans_item_time"  
    30.             android:layout_width="wrap_content"  
    31.             android:layout_height="wrap_content"  
    32.             android:layout_below="@id/ans_item_locname"  
    33.             android:layout_toRightOf="@id/a4" />  
    34.     RelativeLayout>  
    35.   
    36. RelativeLayout>  

     

    1. public class AnsList extends ListActivity {  
    2.   
    3.     private PoiDbAdapter dba = null;  
    4.     private Cursor cursor = null;  
    5.     private ListView listView = null;  
    6.   
    7.     @Override  
    8.     protected void onCreate(Bundle savedInstanceState) {  
    9.         super.onCreate(savedInstanceState);  
    10.         setContentView(R.layout.ans_list);  
    11.         // 初始化标题   
    12.         ...  
    13.   
    14.         // 初始化列表   
    15.         initList();  
    16.         if (listView == null || listView.getCount() < 1) {  
    17.             findViewById(R.id.ans_foot).setVisibility(View.GONE);  
    18.         } else {  
    19.             initEvents();  
    20.         }  
    21.     }  
    22.   
    23.     /** 初始化列表 */  
    24.     private void initList() {  
    25.         listView = getListView();  
    26.         dba = new PoiDbAdapter(this);  
    27.         cursor = dba.selectAnsByQnaire(QNaireBuilder.getQnaire(null)  
    28.                 .getQnaireId());  
    29.         startManagingCursor(cursor);  
    30.             // 构造游标适配器   
    31.         MyCursorAdapter adapter = new MyCursorAdapter(this, R.layout.ans_item,  
    32.                 cursor, new String[] { ARemoteId, ALongi, ALati, ALocName,  
    33.                         ATime }, new int[] { R.id.ans_item_num,  
    34.                         R.id.ans_item_longi, R.id.ans_item_lati,  
    35.                         R.id.ans_item_locname, R.id.ans_item_time });  
    36.         // 自定义ViewBinder,日期类型的数据需要转换   
    37.         adapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {  
    38.             public boolean setViewValue(View view, Cursor cursor,  
    39.                     int columnIndex) {  
    40.                 String text = cursor.getString(columnIndex);  
    41.                 if (cursor.getColumnName(columnIndex).equalsIgnoreCase(ATime)) {  
    42.                     text = TimeTools.formatTime(Long.valueOf(text));  
    43.                 }  
    44.                 if (view instanceof TextView) {  
    45.                     ((TextView) view).setText(text);  
    46.                 }  
    47.                 return true;  
    48.             }  
    49.         });   
    50.         setListAdapter(adapter);  
    51.     }  
    52.   
    53.     /** 为按钮和复选框添加事件处理, 为列表添加事件 */  
    54.     private void initEvents() {  
    55.           
    56.                  ....  
    57.   
    58.         ((CheckBox) findViewById(R.id.ans_cbx_select))  
    59.                 .setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {  
    60.                     @Override  
    61.                     public void onCheckedChanged(CompoundButton buttonView,  
    62.                             boolean isChecked) {  
    63.                         selectAllOrNot(isChecked);  
    64.                     }  
    65.                 });  
    66.   
    67.     }  
    68.   
    69.     ...  
    70.   
    71.     /** 全选或全部不选 */  
    72.     protected void selectAllOrNot(boolean isChecked) {  
    73.         int count = listView.getChildCount();  
    74.         for (int i = 0; i < count; i++) {  
    75.             ((CheckBox) ((listView.getChildAt(i))  
    76.                     .findViewById(R.id.ans_item_select))).setChecked(isChecked);  
    77.         }  
    78.         ((MyCursorAdapter) listView.getAdapter()).selectAll(isChecked);  
    79.     }  
    80.   
    81.     ...  
    82.   
    83.   
    84.     @Override  
    85.     protected void onListItemClick(ListView l, View v, int position, long id) {  
    86.           
    87.         CheckBox cbx = (CheckBox) v.findViewById(R.id.ans_item_select);  
    88.         if (cbx != null) {  
    89.             cbx.toggle();  
    90.             ((MyCursorAdapter) l.getAdapter())  
    91.                     .select(position, cbx.isChecked());  
    92.         }         
    93.     }  
    94.   
    95. }  


    1. // 自定义ListAdapter   
    2.   
    3. public class MyCursorAdapter extends SimpleCursorAdapter {  
    4.   
    5.     private HashMap isSelected = null;  
    6.   
    7.     public MyCursorAdapter(Context context, int layout, Cursor c,  
    8.             String[] from, int[] to) {  
    9.         super(context, layout, c, from, to);  
    10.         isSelected = new HashMap();  
    11.         selectAll(false);  
    12.     }  
    13.   
    14.   
    15.     // ListView加载新的Item的时候会调用这个方法   
    16.     // 在加载前设置好意境保存好的Checkbox的状态   
    17.     @Override  
    18.     public View getView(int position, View convertView, ViewGroup parent) {  
    19.         convertView = super.getView(position, convertView, parent);  
    20.         Boolean b = isSelected.get(position);  
    21.         if (null == b)  
    22.             b = false;  
    23.         if (convertView instanceof ViewGroup) {  
    24.             ViewGroup g = (ViewGroup) convertView;  
    25.             for (int i = 0; i < g.getChildCount(); i++) {  
    26.                 View v = g.getChildAt(i);  
    27.                 if (v instanceof CheckBox) {  
    28.                     ((CheckBox) v).setChecked(b);  
    29.                     break;  
    30.                 }  
    31.             }  
    32.         }  
    33.         return convertView;  
    34.     }  
    35.   
    36.     public void select(int postion, boolean isChecked) {  
    37.         isSelected.put(postion, isChecked);  
    38.     }  
    39.   
    40.     public void selectAll(boolean isChecked) {  
    41.         int a = this.getCount();  
    42.         for (int b = 0; b < a; b++) {  
    43.             select(b, isChecked);  
    44.         }  
    45.     }  
    46. }  

    经过折腾之后,终于顺利通过调试,可以轻松实现全选批量操作,




原文链接: http://blog.csdn.net/hopezhangbo/article/details/7356550

转载于:https://my.oschina.net/chen106106/blog/51717

你可能感兴趣的:(解决 Android 中使用ListView和CheckBox批量操作时若干问题)