RecyclerView + CheckBox勾選混亂及焦點問題

RecyclerView 為了提高效率,其內(nèi)部使用了Recycler回收機制,原理是將上方的 itemView 銜接下次使用,僅加載數(shù)據(jù),從而達(dá)到View的復(fù)用。


問題描述

項目中涉及 RecyclerView 中包含 CheckBox 時。

  • 首先遇到是焦點問題,主要是CheckBox搶占了焦點,造成點擊事件無法響應(yīng)的問題。
  • 其次遇到CheckBox多選時,滑動狀態(tài)錯亂問題
焦點解決方案

為父級元素設(shè)置 android:descendantFocusability

屬性值 作用
beforeDescendants viewgroup會優(yōu)先其子類控件而獲取到焦點
afterDescendants viewgroup只有當(dāng)其子類控件不需要獲取焦點時才獲取焦點
blocksDescendants viewgroup會覆蓋子類控件而直接獲得焦點
狀態(tài)錯亂解決方案
方案一

原理:使用SparseBooleanArray(少量數(shù)據(jù)比HashMap效率更高,原因是其key的類型為 int 型,相比HashMap少了封箱過程)存儲選中的狀態(tài)值,根據(jù)position獲取。


//存儲選中狀態(tài)
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));
}

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

方案二

原理:將CheckBox 的OnCheckedChangeListener 置空(因為當(dāng)view滑出致checkbox 的可視范圍時,OnCheckedChangeListener事件會被觸發(fā)),重新設(shè)置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());
  });
}

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


注:以上便是RecyclerView和CheckBox的坑,具體使用哪個方案可根據(jù)實際問題選擇。


沒有最好,只有最合適
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容