如何实现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
相关产品推荐
相关产品推荐

