在 Android RecyclerView 中处理多选

Handling Multiselection in Android RecyclerView

我对 RecyclerView 状态 selected/unselected 中的项目使用 onLongClickListener,并更改项目背景颜色。选择工作正常,但列表下方的一些其他项目也改变了颜色(尽管它们的状态保持 'unselected')。我怀疑问题是由于 viewholder 被重用造成的,但我不知道如何解决。我按照 实现了多选,这是我在应用程序中绝对需要的。

public class TasksPagedAdapter extends PagedListAdapter<Task, TaskViewHolder> {

private static DiffUtil.ItemCallback<Task> DIFF_CALLBACK = new DiffUtil.ItemCallback<Task>() {
    @Override
    public boolean areItemsTheSame(@NonNull Task task, @NonNull Task t1) {

        return task.getId() == t1.getId();
    }

    @Override
    public boolean areContentsTheSame(@NonNull Task task, @NonNull Task t1) {
        return task.equals(t1);
    }
};

private ItemClickListener itemClickListener;

protected TasksPagedAdapter(ItemClickListener itemClickListener) {
    super(DIFF_CALLBACK);

    setHasStableIds(true);
    this.itemClickListener = itemClickListener;
}

@NonNull
@Override
public TaskViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int position) {

    View itemRootView = LayoutInflater
            .from(parent.getContext())
            .inflate(R.layout.item_tarea, parent, false);

    return new TaskViewHolder(itemRootView);
}

@Override
public void onBindViewHolder(@NonNull TaskViewHolder taskViewHolder, int position) {

    Task taskItem = getItem(position);

    int importancia = taskItem.getImportancia();
    switch (importancia) {
        case 0:
            taskViewHolder.iv_importancia.setImageResource(R.drawable.icon_importancia_0);
            break;
        case 1:
            taskViewHolder.iv_importancia.setImageResource(R.drawable.icon_importancia_1);
            break;
        case 2:
            taskViewHolder.iv_importancia.setImageResource(R.drawable.icon_importancia_2);
            break;
        case 3:
            taskViewHolder.iv_importancia.setImageResource(R.drawable.icon_importancia_3);
            break;
        case 4:
            taskViewHolder.iv_importancia.setImageResource(R.drawable.icon_importancia_4);
            break;
        default:
            taskViewHolder.iv_importancia.setImageResource(R.drawable.icon_importancia_0);
            break;
    }
    taskViewHolder.tv_asunto.setText(taskItem.getAsunto());
    taskViewHolder.tv_fecha_creacion.setText(taskItem.getFechaCreacion());
    taskViewHolder.item_container.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            itemClickListener.onItemClick(position);
        }
    });
    taskViewHolder.item_container.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            itemClickListener.onItemLongClick(position);

            taskItem.setSelected(!taskItem.isSelected());
            taskViewHolder.item_container.setBackgroundColor(taskItem.isSelected() ? Color.CYAN : Color.WHITE);

            return true;
        }
    });
}

public Task getListItem(int position) {
    return getItem(position);
}

public List<Integer> getSelectedTasks() {
    List<Integer> selectedTasksIds = new ArrayList<>();
    for (Task task : getCurrentList().snapshot()) {
        if (task.isSelected()) {
            selectedTasksIds.add(task.getId());
        }
    }
    return selectedTasksIds;
}

@Override
public long getItemId(int position) {
    return position;
}

}

在recyclerview适配器中添加这两个方法

 override fun getItemId(position: Int): Long {
        return position.toLong()
    }

    override fun getItemViewType(position: Int): Int {
        return position
    }

像这样在您的适配器 class 中覆盖这些方法。

@Override
public long getItemId(int position) {
 return position;
}

@Override
public int getItemViewType(int position) {
 return position;
}

RecyclerView 将重用视图来填充数据。

只需将此行 taskViewHolder.item_container.setBackgroundColor(taskItem.isSelected() ? Color.CYAN : Color.WHITE); 添加到 onBindViewHolder 即可修复(当您滚动时将设置正确的颜色)