场景:当ListView中嵌套CheckBox,在滑动过程中,遇到滑动过程中,CheckBox选中状态错乱。
分析:ListView在滑动过程中,每个item都需要调用getView(int position, View convertView, ViewGroup parent)方法,而这个方法传入的 convertView 是在屏幕滑动过程中不断复用的,以减少 item 重新创建的内存消耗。但同时由于 convertView 的复用,也造成了我们的 CheckBox 展示状态默认复用前的状态。我们平时在 ListView 中出现的滑动过程中图片加载 闪烁也是同理。
优化方案:
本文仅以 ListView 支持单选为例:
1. 在实体类中添加一个参数:
public boolean is_Checked = false;
2. 在Adapter添加CheckBox状态监听
// 默认选中下标 private int index = -1;
@Override protected View getView(final int position, View convertView, ViewGroup parent) { ViewHolder viewHolder = null; if (convertView == null) { viewHolder = new ViewHolder(); convertView = mInflater.inflate(R.layout.item_related_fields_left, null); viewHolder.cbTitle = (CheckBox) convertView.findViewById(R.id.tv_relative_fields_tag); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } CircleEntity circleEntity = mList.get(position); viewHolder.cbTitle.setText(circleEntity.name); viewHolder.cbTitle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton compoundButton, boolean b) { if (b){ if (index != -1 ){ //判断是否被选中 mList.get(index).is_Checked = false; } index = position; mList.get(index).is_Checked = true; mIOnCurrentFragment.currentIndex(position); notifyDataSetChanged(); }else { if (index == position) { // 禁止取消当前项 compoundButton.setChecked(true); } } } }); //无默认选中项时:默认选中第一个 if (index == -1) index= position; if (index == position) viewHolder.cbTitle.setChecked(true); else viewHolder.cbTitle.setChecked(circleEntity.is_Checked); return convertView; }
public class ViewHolder { public CheckBox cbTitle; }
此方案适用于商品选择标签,(ListView + Fragment) 进行左右联动的场景