解决ListView中CheckBox复用而选中状态消失的问题

ListView中使用CheckBox

ListView出于内存优化的考虑,android为我们提供了convertView。可是复用item,会使CheckBox的选中状态错乱。下面为大家讲解一下,我是怎样处理的。

这次我接到的需求是如图所示:

并且,下次进入要把选中的状态携带进来。
我最先想到的处理办法是ListView与CheckBox结合,但是这样做的话便会出现,如下两个问题:

1.当我ListView上下滑动的时候,选中状态会错乱;
2.当我携带一组选中状态进入到ListView的时候,状态没有绘制成功。

其实这两个问题,可以归结为一个,就是ListView复用导致的.
有一些博客可能会教大家在adapter中写一个Map,保存每个条目的选中与未选中的状态,但是我亲测过程中出现一些问题,由于时间久远我记不清是上述两点中的哪个未被解决了。现提供一个比较简单的办法来处理ListView与CheckBox之间的冲突。

当屏幕中只能展示ListView的10个item,当第11个item滑出是,它复用的是第1个item,但是由于setChecked()方法会触发监听器,而此时,第11个的item触发的是第1个item的中CheckBox的监听器,这也就导致了,第1个item中的CheckBox执行了onCheckedChanged(),所以也就出现了错乱的问题。但是如果先设置监听又会让CheckBox多出许多选中状态,同样会出现错乱。
现在我们已经知道是监听器的原因了,所以我们可以在setChecked()之前先清空监听,防止干扰setChecked()对CheckBox的状态进行设置。我们只需在setChecked()之前加上一句

holder.cb.setOnCheckedChangeListener(null)

这样就可以了。

下面贴上我自己的代码(需求,选中状态是由外部传入,然后在ListView中做展示,并可修改各个item的选中状态)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//adapter中的getView()的部分代码
//从外部传入选中的Id
if (mCheckList!=null){
holder.cb.setOnCheckedChangeListener(null);
if (mCheckList.contains(child.getId())){
holder.cb.setChecked(true);
}else{
holder.cb.setChecked(false);
}
}else{
mCheckList = new ArrayList<>();
}
//给CheckBox设置监听
holder.cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked){
//如果选中,加入选中状态的list
mCheckList.add(String.valueOf(child.getId()));
}else{
//如果取消选中,把选中的id从list中移除
mCheckList.remove(child.getId());
}
//此为给activity的回调,把选中的所有CheckBox组成list还给activity
if (onCheckListener!=null){
onCheckListener.onCheckedChange(mCheckList);
}
}
});

Adapter怎样给Activity提供接口

由于上面提到adapter和activity互传数据的问题,以下为怎样给activity提供接口,供activity回调adapter中数据,不想把activity和adapter写在一个activity中的童鞋可以借鉴一下:

1
2
3
4
5
6
7
8
9
//写在adapter中暴露给activity的接口
public interface OnCheckListener{
public void onCheckedChange(List<String> list);
}
OnCheckListener onCheckListener;
public void setOnCheckListener(OnCheckListener onCheckListener){
this.onCheckListener = onCheckListener;
}

1
2
3
4
5
6
7
//activity中使用的方法
OnCheckListener onCheckListener = new OnCheckListener() {
@Override
public void onCheckedChange(List adapterCheckedList) {
mCheckIdList = adapterCheckedList;
}
};

如需转载,请注明出处:YauLam’s Blog,thank u~