Ответ 1
Вы видите это поведение, потому что ViewHolder
повторно используются. После прокрутки вниз ViewHolder
верхних элементов (которые теперь не видны) будут повторно использоваться для новых элементов, которые будут отображаться. Этот ViewHolder
имел CheckBox
, который был проверен ранее, и никто прямо не сказал, что он должен быть снят.
Вы должны позаботиться о правильном восстановлении состояния. Вы можете сохранить отмеченные позиции позиций в массиве, а затем в onBindViewHolder()
соответствующим образом установить выбранное состояние CheckBox
:
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);
}
...
}
Или вы можете воздержаться от "переосмысления колеса" и использовать MultiViewAdapter
, который отправляется с checkboxes: одиночная, одиночная или ни одна, несколько режимов.