一.RecyclerView + CheckBox勾选混乱问题解决
RecyclerView中使用CheckBox时因为RecyclerView布局会重用,所以在勾选时出现勾选混乱。如图
勾选 0号位和2号位 21 23也被勾选了。
此时适配器中的代码
@Override public void onBindViewHolder(ViewHolder holder, final int position) { holder.mTextView.setText(mList.get(position)); }
想要解决勾选混乱问题,可以使用集合添加被勾选的CheckBox位置,然后集合中有的位置则设置为被勾选,没有的位置就设置不被勾选
效果如下:勾选 0 1 2 位置,并未出现勾选混乱
此时的代码
private Map, Boolean> map = new HashMap<>(); @Override public void onBindViewHolder(ViewHolder holder, final int position) { holder.mTextView.setText(mList.get(position)); holder.mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked == true) { map.put(position, true); } else { map.remove(position); } } }); if (map != null && map.containsKey(position)) { holder.mCheckBox.setChecked(true); } else { holder.mCheckBox.setChecked(false); } }
二.ReyclerView+CheckBox实现单选功能
方法:在每次设置CheckBox为true时,都将存有勾选的CheckBox的位置的集合清空,然后在将当前CheckBox加入进去,在通知适配器更新。
效果如下:
错误示例:
private Map, Boolean> map = new HashMap<>(); @Override public void onBindViewHolder(ViewHolder holder, final int position) { holder.mTextView.setText(mList.get(position)); holder.mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked == true) { map.clear(); map.put(position, true); } else { map.remove(position); } notifyDataSetChanged(); } }); if (map != null && map.containsKey(position)) { holder.mCheckBox.setChecked(true); } else { holder.mCheckBox.setChecked(false); } }
异常:java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling
提示说:不能在RecyclerView计算layout或者滑动的时候使用 notifyDataSetChanged() 方法
解决问题:添加判断条件,不在RecycerView计算layout或滑动的时候 通知适配器更新
private boolean onBind; @Override public void onBindViewHolder(ViewHolder holder, final int position) { holder.mTextView.setText(mList.get(position)); holder.mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked == true) { map.clear(); map.put(position, true); } else { map.remove(position); } if (!onBind) { notifyDataSetChanged(); } } }); onBind = true; if (map != null && map.containsKey(position)) { holder.mCheckBox.setChecked(true); } else { holder.mCheckBox.setChecked(false); } onBind = false; }
三.获取CheckBox勾选的位置
完整的适配器代码:
public class CheckBoxAdapter extends RecyclerView.Adapter{ private List mList; private Context mContext; private Map , Boolean> map = new HashMap<>(); private boolean onBind; private int checkedPosition = -1; public CheckBoxAdapter(Context context, List list) { this.mContext = context; this.mList = list; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(mContext).inflate(R.layout.item_rcy_checkbox, parent, false); return new ViewHolder(view); } //得到当前选中的位置 public int getCheckedPosition() { return checkedPosition; } @Override public void onBindViewHolder(ViewHolder holder, final int position) { holder.mTextView.setText(mList.get(position)); holder.mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked == true) { map.clear(); map.put(position, true); checkedPosition = position; } else { map.remove(position); if (map.size() == 0) { checkedPosition = -1; //-1 代表一个都未选择 } } if (!onBind) { notifyDataSetChanged(); } } }); onBind = true; if (map != null && map.containsKey(position)) { holder.mCheckBox.setChecked(true); } else { holder.mCheckBox.setChecked(false); } onBind = false; } @Override public int getItemCount() { return mList.size(); } class ViewHolder extends RecyclerView.ViewHolder { CheckBox mCheckBox; TextView mTextView; public ViewHolder(View itemView) { super(itemView); mCheckBox = (CheckBox) itemView.findViewById(R.id.checkbox); mTextView = (TextView) itemView.findViewById(R.id.textView); } } }