Checkbox becoming 'sticky' in RecyclerView

人盡茶涼 提交于 2019-12-12 05:58:31

问题


I have a dialog which takes in user input through a list with checkboxes, whose layout is a RecyclerView. But when I select a CheckBox in the list, another CheckBox further down in the list also gets checked, but which I didn't do. These images will help illustrate my point.

Here, I've only selected Calendar and Camera:

but further down in the list, Google and Maps also get selected which I didn't select.

My code for bindActivity is:

public void bindActivity(ResolveInfo resolveInfo)
        {
            mResolveInfo = resolveInfo;
            PackageManager pm = getActivity().getPackageManager();
            String appName = mResolveInfo.loadLabel(pm).toString();
            mAppImageView.setImageDrawable(resolveInfo.loadIcon(pm));
            mAppTextView.setText(appName);
        }

If I add mAppCheckBox.setChecked(false) in bindActivity, then when i go further down in the list and the RecyclerView 'recycles' the list, and then I go up, my earlier selection becomes unselected.

I would love any suggestions on how to get rid of the 'sticky' checkbox.


回答1:


You see that behavior, because ViewHolders are being reused. Once you scroll down, the ViewHolder of the upper items (that are not visible now) will be reused for the new items that are going to be displayed. This ViewHolder had a CheckBox that was checked previously and nobody had explicitly said, that it should be unchecked.

You should take care of resetting the state correctly. You can save checked items positions in an array and later in onBindViewHolder() set the selected state of CheckBox appropriately:

public class MyAdapter extends RecyclerView.Adapter<Item> {

  final boolean[] checkedArr;

  public MyAdapter(List<Item> list) {
    checkedArr = new boolean[list.size()];
    // Filling all the items as unchecked by default
    Arrays.fill(checkedArr, false);
  }

  @Override public void onBindViewHolder(Item holder, int position) {
    // You have removed the listener in `onViewRecycled`
    // Thus, this `setChecked()` won't cause any listener to be fired
    holder.checkbox.setChecked(checkedArr[holder.getAdapterPosition()]);
    holder.checkbox.setOnCheckedChangeListener(
        (buttonView, isChecked) -> {
          // Retaining checked state in the array
          checkedArr[holder.getAdapterPosition()] = isChecked;
        });
  }

  @Override public void onViewRecycled(Item holder) {
    super.onViewRecycled(holder);
    // When view is being recycled remove the listener
    holder.checkbox.setOnCheckedChangeListener(null);
  }
  ...
}

Or you can refrain from "reinventing a wheel" and use MultiViewAdapter that is shipping with checkboxes feature: single, single or none, multiple modes.




回答2:


a) It doesn't look like you are setting the checked state of the checkbox when you are binding the view. Keep track of the items that have been selected, and then set the checked state when you doing view binding.

b) I'm not exactly sure what you mean, but from what I gather, the dialog documenation might be what you are looking for when communicating with the parent.



来源:https://stackoverflow.com/questions/44613942/checkbox-becoming-sticky-in-recyclerview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!