问题
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 ViewHolder
s 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