这是一个很普遍的情况,ListView的每一个View中包含CheckBox控件,在滑动屏幕时,原来点选的CheckBox貌似会发生变化,莫名其妙地乱窜:原来选中的变为没选中;原来没选中的变成选中,每滑动一下,就改变一次。
我们先来分析一下CheckBox会错乱的原因,我们在显示ListView的每一个View时,使用的是BaseAdapter的getView()方法,getView()方法的第二个参数View convertView,是会被重复使用的,也就是当滑动时产生新的View时,首先判断convertView是否为null,为null则inflate,不为null就使用已经生成的convertView。
知道了问题产生的原因,我们来说一下解决问题的思路。我一共想了两种解决策略:
1:第一次生成convertView时,保存到一个ArrayList<HashMap<Integer,View>> vmap中,Integer为该convertView对应的position,下一次getView()时,通过vmap.get(position)取得已经存在的convertView,代码如下:
private SparseArray<View> vmap = new SparseArray<View>();
@Override
public View getView(int position, View convertView, android.view.ViewGroup parent){
viewHolder viewholder = null;
//Inflate view
if(vmap.get(position)==null){
viewholder = new viewHolder();
convertView = mInflater.inflate(R.layout.list_item,null);
viewholder.waybill = (TextView)convertView.findViewById(R.id.waybill);
viewholder.addtime = (TextView)convertView.findViewById(R.id.addtime);
viewholder.checkbox = (CheckBox)convertView.findViewById(R.id.checkbox);
convertView.setTag(viewholder);
vmap.put(position, convertView);
}else{
convertView = vmap.get(position);
viewholder = (viewHolder)convertView.getTag();
}
return convertView;
}
/**
* 私有化View控件
*/
public static class viewHolder{
public TextView waybill;
public TextView addtime;
public CheckBox checkbox;
}
这种方法可以解决CheckBox状态错乱的问题,但是有一个问题:有时候点击了CheckBox后,必须要滑动屏幕CheckBox的状态才会生效,还没有找到解决方法。
2:设置CheckBox的setOnCheckedChangeListener()事件,将每一个CheckBox的状态保存到一个ArrayList<HashMap<Integer,boolean>>数组中,Integer为该convertView对应的position,代码如下:
public static SparseBooleanArray checked = new SparseBooleanArray();
@Override
public View getView(int position, View convertView, android.view.ViewGroup parent){
viewHolder viewholder = null;
//Inflate view
if(convertView == null){
viewholder = new viewHolder();
convertView = mInflater.inflate(R.layout.list_item,null);
viewholder.waybill = (TextView)convertView.findViewById(R.id.waybill);
viewholder.addtime = (TextView)convertView.findViewById(R.id.addtime);
viewholder.checkbox = (CheckBox)convertView.findViewById(R.id.checkbox);
convertView.setTag(viewholder);
}else{
viewholder = (viewHolder)convertView.getTag();
}
final int mposition = position;
viewholder.checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener(){
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
//TODO Auto-generated method stub
if(isChecked)
{
checked.put(mposition, isChecked);
}else{
checked.delete(mposition);
}
}
});
//根据保存的状态设置CheckBox
viewholder.checkbox.setChecked(checked.get(position)==true ? true : false);
}
/**
* 私有化View控件
*/
public static class viewHolder{
public TextView waybill;
public TextView addtime;
public CheckBox checkbox;
}