Android:CursorAdapter,ListView和CheckBox

我有我自己的布局和CustomCursorAdapter的ListView。 每一行都有自己的checkbox。 所以…很明显,在滚动期间,checkbox会松动它们的状态。 我发现唯一的东西是Android保存checkbox状态ListView与光标适配器,但没有答案。 还有一个问题。 我与我的CustorArrayAdapter有同样的问题。 我解决了这个问题,使用SparseBooleanArray保持checkbox的状态。 它工作正常,但每个滚动调用onCheckedChanged。 这很正常吗? 交易是我的列表视图描述报警元素和定期调用(onCheckedChanged)启动/停止报警。 许多不合时宜的行为。

当ListView中有可检查的项目时,有一些问题。 我会build议以下链接:

http://tokudu.com/2010/android-checkable-linear-layout/

我认为这是接近你想要的。

我有我的ListViewCheckBox类似的问题,我做了什么来摆脱这个问题:

  • 创build一个布尔对象的ArrayList来存储每个CheckBox的状态
  • 初始化ArrayList项目为默认值false ,意味着没有checkbox被检查。
  • 当你点击checkbox。 设置对检查/未检查状态的检查,并将该值存储在ArrayList中。
  • 现在使用setChecked()方法将该位置设置为CheckBox。

看到这段代码片段:

 public class MyDataAdapter extends SimpleCursorAdapter { private Cursor c; private Context context; private ArrayList<String> list = new ArrayList<String>(); private ArrayList<Boolean> itemChecked = new ArrayList<Boolean>(); // itemChecked will store the position of the checked items. public MyDataAdapter(Context context, int layout, Cursor c, String[] from, int[] to) { super(context, layout, c, from, to); this.c = c; this.context = context; for (int i = 0; i < this.getCount(); i++) { itemChecked.add(i, false); // initializes all items value with false } } public View getView(final int pos, View inView, ViewGroup parent) { if (inView == null) { LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); inView = inflater.inflate(R.layout.your_layout_file, null); } final CheckBox cBox = (CheckBox) inView.findViewById(R.id.bcheck); // your // CheckBox cBox.setOnClickListener(new OnClickListener() { public void onClick(View v) { CheckBox cb = (CheckBox) v.findViewById(R.id.your_checkbox_id); if (cb.isChecked()) { itemChecked.set(pos, true); // do some operations here } else if (!cb.isChecked()) { itemChecked.set(pos, false); // do some operations here } } }); cBox.setChecked(itemChecked.get(pos)); // this will Check or Uncheck the // CheckBox in ListView // according to their original // position and CheckBox never // loss his State when you // Scroll the List Items. return inView; }} 

我也面临着类似的问题,所以经过大量的阅读,我解决了这个问题:

 @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if (convertView == null) { convertView = mInflater.inflate(R.layout.listview, null); holder = new ViewHolder(); holder.nameView = (TextView)convertView.findViewById(R.id.textView1); holder.numberView = (TextView)convertView.findViewById(R.id.textView2); holder.cb = (CheckBox)convertView.findViewById(R.id.checkBox1); convertView.setTag(holder); } else { holder = (ViewHolder)convertView.getTag(); } holder.nameView.setText(mData.get(position).toString()); holder.numberView.setText(mNumber.get(position).toString()); holder.cb.setChecked(false); holder.cb.setTag(position); if(selected.indexOf(mNumber.get(position).toString()) >= 0) { holder.cb.setChecked(true); } return convertView; } } 

在这里,我正在做的getView()我没有选中所有的checkbox,并再次手动检查我需要根据它对应的文本检查检查。 因此,如果用户在查看第一个checkbox后向下滚动,则视图中的所有checkbox都将被取消选中,如果再次向上滚动,则所有checkbox都将被取消选中,但是之前单击的checkbox将被再次复选。

我决定尝试使用setViewBinder方法。 Сheckboxes状态存储在SparseBooleanArray中。 当您单击checkbox本身以及整个单元格时,heckbox状态会发生变化。

我的行:| TextView | CheckBox |

 public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // .. private SparseBooleanArray checkedItems = new SparseBooleanArray(); //for storing item state startManagingCursor(cursor); String[] from = new String[] { dbAdapter.COLUMN_NAME, dbAdapter.COLUMN_CHECK }; int[] to = new int[] { R.id.item_name, R.id.item_check }; recordsAdapter = new SimpleCursorAdapter(this, R.layout.items, cursor, from, to); recordsAdapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() { public boolean setViewValue(View view, Cursor cursor, int columnIndex) { if (columnIndex == 2) { //2 - R.id.item_check final CheckBox cb = (CheckBox) view; final int rowID = cursor.getInt(0); //cursor.getInt(0) - _id from table if (checkedItems.indexOfKey(rowID) >= 0) { //checkedItems contains rowID? cb.setChecked(checkedItems.get(rowID)); } else if (cursor.getInt(2) > 0) { //cursor.getInt(2): 0 - false, 1 - true checkedItems.append(rowID, true); cb.setChecked(true); } else { cb.setChecked(false); } cb.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (checkedItems.indexOfKey(rowID) >= 0) { checkedItems.put(rowID, !(checkedItems.get(rowID))); } else { checkedItems.append(rowID, true); } cb.setChecked(checkedItems.get(rowID)); dbAdapter.updateItem(rowID, checkedItems.get(rowID)?1:0); } }); return true; } return false; } }); itemsList.setAdapter(recordsAdapter); itemsList.setOnItemClickListener(this); // .. } //if click on TextView of row - CheckBox of row is set/unset @Override public void onItemClick(AdapterView<?> parent, View view, int pos, long id) { TextView tv = (TextView) view.findViewById(R.id.item_name); ViewGroup row = (ViewGroup) tv.getParent(); CheckBox cb = (CheckBox) row.getChildAt(1); cb.performClick(); } 

我无法理解,为什么它不可能(如在HTML中)将一个ViewElement定义为XML中的一个数组。 即:

 <CheckBox android:id="@+id/myCheckBox[]" android:focusable="false" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true" /> 

并存储一个值int it [true | false]。 这会让生活变得更容易,而不是使用复杂的源泉。 此外,数据(即从横向切换到肖像时)应由android保存,不要迷路。

也许在API 117,版本toothscratch …

(sry,目前还不能评论) – 关于Vikas Patidar的答案,对我很有帮助 – 在使用asynchronous加载(比如使用Loader)时要注意,因为Adapter的构造函数中的getCount将为零。

最终导致索引错误(导致ArrayList永远不会被填充)。 使用SparseBooleanArray而不是ArrayList,它也可以用于asynchronous加载。

可能在这里迟到,加上Vikas Patidar的答案在这里是一个完整的实现使用bindView方法为你的那些起诉一个CursorAdapter:

 @Override public void bindView(View view, Context context, Cursor cursor) { final ViewHolder holder = (ViewHolder) view.getTag(); final int position = cursor.getPosition(); String name = (cursor.getString(cursor.getColumnIndexOrThrow("NotificationDateFor"))); String image = cursor.getString(cursor.getColumnIndexOrThrow("imageUri")); System.out.println("cursor.getPosition(test): "+cursor.getPosition()); holder.nametext.setText(name); // setImage(image, holder.iv); holder.chk.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { if (holder.chk.isChecked()) { itemChecked.set(position, true); System.out.println("cursor.getPosition(true): "+position); } else if (!holder.chk.isChecked()) { itemChecked.set(position, false); System.out.println("cursor.getPosition(false): "+position); // AddDelete } } }); holder.chk.setChecked(itemChecked.get(cursor.getPosition())); } 

注意: final int position = cursor.getPosition(); 很重要!

利用Listview的内置多选模式,您可以省去很多麻烦。

listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);