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

如何实现RecyclerView网格项点击选中/取消选中的交互逻辑

网格布局RecyclerView单选切换高亮实现

实现逻辑说明

这个交互是带取消功能的单选模式,不需要给每个条目单独维护选中状态,靠一个全局位置变量就能实现,性能开销最低:

  • 初始化时在Adapter中定义选中位置变量,默认值设为-1,代表当前没有任何条目被选中
  • 点击条目时做判断:如果点击的位置和已记录的选中位置相同,说明是点击已变红的条目,直接把选中位置重置为-1;如果点击位置和已记录的选中位置不同,就把选中位置更新为当前点击的条目位置
  • 状态变更时只需要刷新旧选中位置、新选中位置两个条目即可,不用全量刷新整个列表
  • 绑定每个条目的时候,直接拿当前条目位置和全局选中位置做比对:匹配就设红色背景,不匹配就设白色背景,天然保证同一时间只有一个条目是红色

核心伪代码

class GridRvAdapter : RecyclerView.Adapter<GridRvAdapter.ItemHolder>() {
    // 全局记录选中的条目位置,-1为无选中
    private var selectedPosition = -1
    // 示例场景固定10个条目
    private val dataList = List(10) { "第${it+1}个条目" }

    inner class ItemHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val itemRoot: View = itemView.findViewById(R.id.item_root_layout)
    }

    override fun onBindViewHolder(holder: ItemHolder, position: Int) {
        // 绑定视图时直接根据选中位置设置背景
        holder.itemRoot.setBackgroundColor(
            if (position == selectedPosition) Color.RED else Color.WHITE
        )

        // 条目点击逻辑
        holder.itemView.setOnClickListener {
            val clickPos = holder.adapterPosition
            when {
                // 点击已选中的条目:取消选中
                clickPos == selectedPosition -> {
                    val oldSelected = selectedPosition
                    selectedPosition = -1
                    notifyItemChanged(oldSelected)
                }
                // 点击未选中的条目:切换选中
                else -> {
                    val oldSelected = selectedPosition
                    selectedPosition = clickPos
                    // 旧选中项存在时先刷新恢复白色
                    if (oldSelected != -1) notifyItemChanged(oldSelected)
                    // 刷新新选中项改成红色
                    notifyItemChanged(selectedPosition)
                }
            }
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemHolder {
        // 常规加载item布局逻辑
        val view = LayoutInflater.from(parent.context).inflate(R.layout.item_grid, parent, false)
        return ItemHolder(view)
    }

    override fun getItemCount(): Int = dataList.size
}

避坑提示:如果列表后续会做插入、删除、移动操作,数据变更后要及时校验selectedPosition的合法性,避免出现选中位置错位、数组越界的问题。

内容的提问来源于stack exchange,提问作者Bob Redity

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 16:03:33