RecyclerView选中/取消选中时仅交替项变色问题修复咨询
解决RecyclerView列表项选中状态异常问题
问题原因
你当前代码里用了全局的isSelected变量,所有列表项共用同一个选中状态,再加上RecyclerView的ViewHolder复用机制,导致点击操作会混乱地影响多个项,出现只有交替项能切换状态的异常。
修改步骤
- 移除全局状态变量:删除Adapter中的
var isSelected: Boolean? = null,它无法单独记录每个列表项的选中状态。 - 维护独立的选中状态集合:在Adapter内部创建一个集合,用来记录每个选中项的唯一标识(比如
id,比position更可靠,因为position会随列表变化)。 - 绑定ViewHolder时初始化状态:每次绑定列表项时,根据集合中的记录设置背景色和图标状态,避免复用ViewHolder导致的状态错乱。
- 修改点击逻辑:点击时基于当前项的唯一标识切换选中状态,更新集合并刷新对应项。
修改后的代码示例
class NewListAdapter( var activity: NewFragment, var itemListner: AllNewListener ) : ListAdapter<AllContactsSaveList, NewListAdapter.OutagesViewHolder>(DiffCallback()) { var lastText: String? = "" // 用Set存储选中项的id,确保每个项的状态独立 private val selectedIds = mutableSetOf<String>() class DiffCallback : DiffUtil.ItemCallback<AllContactsSaveList>() { override fun areItemsTheSame(oldItem: AllContactsSaveList, newItem: AllContactsSaveList) = oldItem.flagsort == newItem.flagsort override fun areContentsTheSame( oldItem: AllContactsSaveList, newItem: AllContactsSaveList ) = oldItem == newItem } interface AllNewListener { fun onNewAllChatsClick( name: String?, id: String?, position: Int ) } override fun onCreateViewHolder( parent: ViewGroup, viewType: Int ): OutagesViewHolder { return OutagesViewHolder( SelectListItemsBinding.inflate( LayoutInflater.from(parent.context), parent, false ) ) } inner class OutagesViewHolder(viewBinding: SelectListItemsBinding) : RecyclerView.ViewHolder(viewBinding.root) { val sender_msg: TextView = itemView.sender_msggfr val checkgreenicon: ShapeableImageView = itemView.checkgreenicon } override fun onBindViewHolder(holder: OutagesViewHolder, position: Int) { holder.apply { val o: AllContactsSaveList = getItem(position) val currentId = o.id ?: return@apply // 初始化当前项的状态 val isSelected = selectedIds.contains(currentId) if (isSelected) { itemView.setBackgroundColor(Color.parseColor("#2E707070")) checkgreenicon.visibility = View.VISIBLE itemView.onlinecolor?.visibility = View.GONE } else { itemView.setBackgroundColor(Color.parseColor("#00000000")) checkgreenicon.visibility = View.GONE itemView.onlinecolor?.visibility = View.VISIBLE } itemView.setOnClickListener { if (selectedIds.contains(currentId)) { // 取消选中 selectedIds.remove(currentId) itemView.setBackgroundColor(Color.parseColor("#00000000")) checkgreenicon.visibility = View.GONE itemView.onlinecolor?.visibility = View.VISIBLE } else { // 设置选中 selectedIds.add(currentId) itemView.setBackgroundColor(Color.parseColor("#2E707070")) checkgreenicon.visibility = View.VISIBLE itemView.onlinecolor?.visibility = View.GONE } notifyItemChanged(position) itemListner.onNewAllChatsClick(o.name, o.id, position) } } } }
补充说明
- 如果允许修改
AllContactsSaveList数据类,也可以直接在数据类中添加var isSelected: Boolean = false字段,状态和数据绑定更直观。修改后只需在点击时切换o.isSelected的值,并调用notifyItemChanged(position)即可。 - 避免使用
position作为选中标识,列表项增删或排序时position会变化,导致状态错乱,优先使用数据本身的唯一ID(比如flagsort或id)。
内容的提问来源于stack exchange,提问作者Prateek Sharma
相关产品推荐
相关产品推荐

