RecyclerView + CheckBox勾选混乱及焦点问题

RecyclerView 为了提高效率,其内部使用了Recycler回收机制,原理是将上方的 itemView 衔接下次使用,仅加载数据,从而达到View的复用。


问题描述

项目中涉及 RecyclerView 中包含 CheckBox 时。

  • 首先遇到是焦点问题,主要是CheckBox抢占了焦点,造成点击事件无法响应的问题。
  • 其次遇到CheckBox多选时,滑动状态错乱问题
焦点解决方案

为父级元素设置 android:descendantFocusability

属性值 作用
beforeDescendants viewgroup会优先其子类控件而获取到焦点
afterDescendants viewgroup只有当其子类控件不需要获取焦点时才获取焦点
blocksDescendants viewgroup会覆盖子类控件而直接获得焦点
状态错乱解决方案
方案一

原理:使用SparseBooleanArray(少量数据比HashMap效率更高,原因是其key的类型为 int 型,相比HashMap少了封箱过程)存储选中的状态值,根据position获取。


//存储选中状态
private SparseBooleanArray mCheckStates = new SparseBooleanArray();

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
  holder.checkBox.setTag(position);
  holder.checkBox.setOnCheckedChangeListener((v, isChecked) -> {
      int poi = (int) v.getTag();
      if (isChecked) {
        mCheckStates.put(poi, true);
      } else {
        mCheckStates.delete(poi);
      }
  });
  holder.checkBox.setChecked(mCheckStates.get(position));
}

/** 设置全部选中否 */
public void setSelectAll(boolean selectAll) {
  if (list != null) {
     for (int i = 0; i < list.size(); i++) {
        mCheckStates.put(i, selectAll);
      }
      notifyDataSetChanged();
  }
}

方案二

原理:将CheckBox 的OnCheckedChangeListener 置空(因为当view滑出致checkbox 的可视范围时,OnCheckedChangeListener事件会被触发),重新设置OnCheckedChangeListener事件。


@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
  holder.checkBox.setOnCheckedChangeListener(null);
  holder.checkBox.setChecked(data.isSelect());
  holder.checkBox.setOnCheckedChangeListener((v, isChecked) -> data.setSelect(isChecked));
  holder.item.setOnClickListener(v -> {
      data.setSelect(!holder.checkBox.isChecked());
      holder.checkBox.setChecked(data.isSelect());
  });
}

/** 设置全部选中否 */
public void setSelectAll(boolean selectAll) {
  if (list != null) {
     for (int i = 0; i < list.size(); i++) {
        list.get(i).setSelect(selectAll);
      }
      notifyDataSetChanged();
  }
}


注:以上便是RecyclerView和CheckBox的坑,具体使用哪个方案可根据实际问题选择。


没有最好,只有最合适

你可能感兴趣的:(RecyclerView + CheckBox勾选混乱及焦点问题)