解决 Android(安卓)中使用ListView和CheckBox批量操作时若干问题
16lz
2022-06-22
本文可以帮助 完美解决在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.
以下是本人程序片段,仅供参考:
<!-- ans_list.xml --><?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:paddingLeft="8dp" android:paddingRight="8dp" > <TextView android:id="@+id/ans_title" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:gravity="center" android:textSize="15sp" android:textStyle="bold" /> <RelativeLayout android:id="@+id/ans_foot" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:paddingLeft="8sp" android:paddingRight="8sp" > <CheckBox android:id="@+id/ans_cbx_select" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_marginLeft="10sp" android:checked="false" /> <Button android:id="@+id/ans_btn_showInMap" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_toLeftOf="@id/ans_cbx_select" android:text="@string/ans_btn_showInMap" /> </RelativeLayout> <ListView android:id="@android:id/list" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_above="@id/ans_foot" android:layout_below="@id/ans_title" android:drawSelectorOnTop="false" > </ListView> <TextView android:id="@android:id/empty" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center" android:text="@string/ans_list_empty" android:textSize="25sp" android:textStyle="bold" > </TextView></RelativeLayout>
<!-- ans_item.xml --><?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="10sp" > <CheckBox android:id="@+id/ans_item_select" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:focusable="false" android:clickable="false" android:checked="false" android:gravity="center_vertical" /> <RelativeLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" > .... <TextView android:id="@+id/ans_item_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/ans_item_locname" android:layout_toRightOf="@id/a4" /> </RelativeLayout></RelativeLayout>
public class AnsList extends ListActivity {private PoiDbAdapter dba = null;private Cursor cursor = null;private ListView listView = null;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.ans_list);// 初始化标题...// 初始化列表initList();if (listView == null || listView.getCount() < 1) {findViewById(R.id.ans_foot).setVisibility(View.GONE);} else {initEvents();}}/** 初始化列表 */private void initList() {listView = getListView();dba = new PoiDbAdapter(this);cursor = dba.selectAnsByQnaire(QNaireBuilder.getQnaire(null).getQnaireId());startManagingCursor(cursor); // 构造游标适配器MyCursorAdapter adapter = new MyCursorAdapter(this, R.layout.ans_item,cursor, new String[] { ARemoteId, ALongi, ALati, ALocName,ATime }, new int[] { R.id.ans_item_num,R.id.ans_item_longi, R.id.ans_item_lati,R.id.ans_item_locname, R.id.ans_item_time });// 自定义ViewBinder,日期类型的数据需要转换adapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {public boolean setViewValue(View view, Cursor cursor,int columnIndex) {String text = cursor.getString(columnIndex);if (cursor.getColumnName(columnIndex).equalsIgnoreCase(ATime)) {text = TimeTools.formatTime(Long.valueOf(text));}if (view instanceof TextView) {((TextView) view).setText(text);}return true;}}); setListAdapter(adapter);}/** 为按钮和复选框添加事件处理, 为列表添加事件 */private void initEvents() { ....((CheckBox) findViewById(R.id.ans_cbx_select)).setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {selectAllOrNot(isChecked);}});}.../** 全选或全部不选 */protected void selectAllOrNot(boolean isChecked) {int count = listView.getChildCount();for (int i = 0; i < count; i++) {((CheckBox) ((listView.getChildAt(i)).findViewById(R.id.ans_item_select))).setChecked(isChecked);}((MyCursorAdapter) listView.getAdapter()).selectAll(isChecked);}...@Overrideprotected void onListItemClick(ListView l, View v, int position, long id) {CheckBox cbx = (CheckBox) v.findViewById(R.id.ans_item_select);if (cbx != null) {cbx.toggle();((MyCursorAdapter) l.getAdapter()).select(position, cbx.isChecked());}}}
// 自定义ListAdapterpublic class MyCursorAdapter extends SimpleCursorAdapter {private HashMap<Integer, Boolean> isSelected = null;public MyCursorAdapter(Context context, int layout, Cursor c,String[] from, int[] to) {super(context, layout, c, from, to);isSelected = new HashMap<Integer, Boolean>();selectAll(false);}// ListView加载新的Item的时候会调用这个方法// 在加载前设置好意境保存好的Checkbox的状态@Overridepublic View getView(int position, View convertView, ViewGroup parent) {convertView = super.getView(position, convertView, parent);Boolean b = isSelected.get(position);if (null == b)b = false;if (convertView instanceof ViewGroup) {ViewGroup g = (ViewGroup) convertView;for (int i = 0; i < g.getChildCount(); i++) {View v = g.getChildAt(i);if (v instanceof CheckBox) {((CheckBox) v).setChecked(b);break;}}}return convertView;}public void select(int postion, boolean isChecked) {isSelected.put(postion, isChecked);}public void selectAll(boolean isChecked) {int a = this.getCount();for (int b = 0; b < a; b++) {select(b, isChecked);}}}
经过折腾之后,终于顺利通过调试,可以轻松实现全选批量操作,
运行效果如下:
@plusplus1
更多相关文章
- 移植 android, touch screen 不能正常工作的问题
- Android(安卓)RSA与Java RSA加密不同标准产生问题的解决方法
- Android应用如何支持屏幕多尺寸多分辨率问题
- android 关于appcompat v7出错问题与解决
- 学习android的一些套路(转发之小黑屋总结)
- Android(安卓)setTag方法的key问题
- android差分更新之服务端
- android 使用socket与pc传递对象的问题
- Android(安卓)Cannas.drawTextView 方法坐标问题