这是一个很普遍的情况,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; }