在ListView嵌套CheckBox 等一些有标记的View时,如果不做处理,在ListView 滑动的时候,
会造成View的选中状态错乱。
比如:
可以看到 刚开始选中了demo2 和demo3。滑动到下一页的时候,demo10 和demo11 也被选中。
当然要解决这个问题很简单。只需要在 适配器Adapter 中对CheckBox的选中状态做一下记录。上代码:
public class MyAdapter extends BaseAdapter{
private List<String> mList;
private Context mContext;
//步骤1
private Map<Integer, Boolean> cbState;// 存放 CheckBox 的选中状态
public MyAdapter(Context mContext,List<String> mList) {
this.mContext=mContext;
this.mList=mList;
cbState=new HashMap<Integer, Boolean>();
}
@Override
public int getCount() {
return mList!=null?mList.size():0;
}
@Override
public Object getItem(int position) {
return mList!=null?mList.get(position):null;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if(convertView==null){
convertView=LayoutInflater.from(mContext).inflate(R.layout.demo_item, parent,false);
holder=new ViewHolder(convertView);
convertView.setTag(holder);
}else{
holder=(ViewHolder)convertView.getTag();
}
holder.textView.setText(mList.get(position));
// 步骤2 对checkbox 的选中状态进行监听,选中时,存入Map 集合,取消选中,则从集合中移除
holder.checkBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked){
cbState.put(position, true);
}else{
cbState.remove(position);
}
}
});
// 步骤3 对Map集合进行判断,处理checkBox 的选中状态
if(cbState!=null&&cbState.containsKey(position)){
holder.checkBox.setChecked(true);
}else{
holder.checkBox.setChecked(false);
}
return convertView;
}
private class ViewHolder{
private TextView textView;
private CheckBox checkBox;
public ViewHolder(View view) {
if(view==null)
return;
textView=(TextView)view.findViewById(R.id.demo_tv);
checkBox=(CheckBox)view.findViewById(R.id.demo_cb);
}
}
}
这样写就可以解决问题。
注意:
如果 步骤2 和步骤3 的顺序写反了,即把对checkBox 的监听方法,写到了checkBox 设置状态的下面了。仍然会导致选中状态错乱。
如图所示:
可以看到 我选中了demo0 和demo1 ,滑下去在滑上来,选中状态就变成了未选中。
通过抓Log,发现,如果两者的顺序写反了,当状态再次改变时,
setOnCheckedChangeListener
监听方法中的position,使用的是上次点击时的postion 。
具体原因还没搞明白,以后会补充。
记住,两者的顺序一定不要写反。要把监听方法写在CheckBox设置状态上面。