You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RecyclerView点击新项后重置旧选中项的实现问题

解决RecyclerView单选时重置前选中项的问题

要实现点击新条目时自动重置之前选中项的状态,核心是记录选中位置,并在onBindViewHolder中统一根据选中状态设置UI样式,而不是只在点击时修改当前项。以下是修改后的完整代码:

public class DateAdapter extends RecyclerView.Adapter<DateAdapter.VH> {
    private List<DateModel> driverListModelList;
    private ClickListener clickListener;
    private int selectedPosition = -1; // 记录选中位置,-1表示无选中项

    public DateAdapter(List<DateModel> driverListModelList, ClickListener clickListener) {
        this.driverListModelList = driverListModelList;
        this.clickListener = clickListener;
    }

    @NonNull
    @Override
    public DateAdapter.VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.date_item, parent, false);
        return new DateAdapter.VH(v);
    }

    @Override
    public void onBindViewHolder(@NonNull DateAdapter.VH holder, int position) {
        DateModel model = driverListModelList.get(position);
        holder.setData(model.getDay(), model.getMonth(), model.getDate());

        // 根据选中状态设置UI样式
        if (position == selectedPosition) {
            // 选中状态
            holder.itemView.setBackground(ContextCompat.getDrawable(holder.itemView.getContext(), R.drawable.day_bar_item2));
            holder.day.setTextColor(Color.WHITE);
            holder.month.setTextColor(Color.WHITE);
            holder.date.setTextColor(Color.WHITE);
        } else {
            // 初始状态,替换成你自己的默认背景和文字颜色
            holder.itemView.setBackground(ContextCompat.getDrawable(holder.itemView.getContext(), R.drawable.day_bar_item));
            holder.day.setTextColor(Color.BLACK);
            holder.month.setTextColor(Color.BLACK);
            holder.date.setTextColor(Color.BLACK);
        }

        // 条目点击事件
        holder.itemView.setOnClickListener(view -> {
            int oldPosition = selectedPosition;
            selectedPosition = holder.getBindingAdapterPosition(); // 获取当前正确的位置(避免ViewHolder复用问题)
            
            // 刷新旧选中项和新选中项
            if (oldPosition != -1) {
                notifyItemChanged(oldPosition);
            }
            notifyItemChanged(selectedPosition);

            // 回调外部点击事件
            clickListener.onItemClicked(selectedPosition);
        });
    }

    @Override
    public int getItemCount() {
        return driverListModelList.size();
    }

    class VH extends RecyclerView.ViewHolder implements View.OnClickListener {
        private TextView day;
        private TextView month;
        private TextView date;

        @SuppressLint("ResourceAsColor")
        public VH(@NonNull View itemView) {
            super(itemView);
            day = itemView.findViewById(R.id.dayTxt);
            month = itemView.findViewById(R.id.txtMonth);
            date = itemView.findViewById(R.id.txtDate);
            itemView.setOnClickListener(this);
        }

        private void setData(final String day, final String month, final String date) {
            this.day.setText(day);
            this.month.setText(month);
            this.date.setText(date);
        }

        @Override
        public void onClick(View view) {
            clickListener.onItemClicked(getAdapterPosition());
        }
    }
}

关键改动说明:

  1. 添加选中位置变量:用selectedPosition记录当前选中的条目位置,初始值设为-1表示无选中项。
  2. 在onBindViewHolder中统一处理样式:每次绑定条目时,根据当前位置是否为选中位置,分别设置选中/初始状态的UI。这解决了ViewHolder复用导致的状态错乱问题。
  3. 精准刷新条目:点击新条目时,先保存旧选中位置,更新新位置后,仅刷新旧选中项和新选中项,比notifyDataSetChanged更高效,也能保证状态正确重置。
  4. 使用getBindingAdapterPosition()获取位置:避免ViewHolder复用导致的位置错误,确保获取到当前条目的真实位置。

你之前调用recyclerView.invalidate()和notifyDataSetChanged()无效的原因是:没有在onBindViewHolder中根据选中状态重置UI,即使刷新所有条目,复用的ViewHolder仍会保持之前修改的样式,无法回到初始状态。

内容的提问来源于stack exchange,提问作者Aaraf Rao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 01:10:34