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

RecyclerView选中/取消选中时仅交替项变色问题修复咨询

解决RecyclerView列表项选中状态异常问题

问题原因

你当前代码里用了全局的isSelected变量,所有列表项共用同一个选中状态,再加上RecyclerView的ViewHolder复用机制,导致点击操作会混乱地影响多个项,出现只有交替项能切换状态的异常。

修改步骤

  1. 移除全局状态变量:删除Adapter中的var isSelected: Boolean? = null,它无法单独记录每个列表项的选中状态。
  2. 维护独立的选中状态集合:在Adapter内部创建一个集合,用来记录每个选中项的唯一标识(比如id,比position更可靠,因为position会随列表变化)。
  3. 绑定ViewHolder时初始化状态:每次绑定列表项时,根据集合中的记录设置背景色和图标状态,避免复用ViewHolder导致的状态错乱。
  4. 修改点击逻辑:点击时基于当前项的唯一标识切换选中状态,更新集合并刷新对应项。

修改后的代码示例

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 12:45:29