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

RecyclerView列表中TextView选中高亮切换异常问题求助

嘿,我来帮你搞定这个RecyclerView选中项切换高亮的问题!你遇到的核心问题其实是没跟踪住上一个选中的位置,再加上RecyclerView的ViewHolder复用特性,导致之前的高亮没法清除。我给你一套完整的解决方案,分步骤来:

核心思路
  • 在Adapter里专门记录当前选中的位置(比如用一个int变量selectedPosition,初始值设为-1表示没有选中项)
  • 点击列表项时,先保存之前的选中位置,再更新为当前点击的位置,最后只刷新这两个位置的视图(避免全局刷新)
  • 在onBindViewHolder()方法里,根据当前绑定的位置是否等于selectedPosition,动态切换文本的加粗样式
具体代码实现

假设你的数据类是包含ID和Value的Item,下面是Adapter的完整示例:

// 你的数据模型类
data class Item(val id: Int, val value: String)

class MyAdapter(private val itemList: List<Item>) : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {
    // 记录当前选中的位置,初始为-1(无选中项)
    private var selectedPosition = -1

    inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val tvId: TextView = itemView.findViewById(R.id.tv_id)
        val tvValue: TextView = itemView.findViewById(R.id.tv_value)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.item_list_layout, parent, false)
        return MyViewHolder(view)
    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        val currentItem = itemList[position]
        holder.tvId.text = currentItem.id.toString()
        holder.tvValue.text = currentItem.value

        // 根据是否为选中位置设置样式
        if (position == selectedPosition) {
            // 选中状态:设置加粗
            holder.tvValue.typeface = Typeface.DEFAULT_BOLD
            // 可选:再加个背景高亮,比如 holder.tvValue.setBackgroundColor(Color.LTGRAY)
        } else {
            // 未选中状态:恢复正常样式
            holder.tvValue.typeface = Typeface.DEFAULT
            // 可选:恢复背景,比如 holder.tvValue.setBackgroundColor(Color.TRANSPARENT)
        }

        // 设置项点击事件
        holder.itemView.setOnClickListener {
            // 先保存之前的选中位置
            val previousSelectedPos = selectedPosition
            // 更新当前选中位置为点击项的位置
            selectedPosition = holder.adapterPosition
            // 只刷新需要变化的两个位置,性能更优
            notifyItemChanged(previousSelectedPos)
            notifyItemChanged(selectedPosition)
        }
    }

    override fun getItemCount(): Int = itemList.size
}
关键细节解释
  • 为什么不用notifyDataSetChanged()?
    全局刷新会重绘整个列表,效率低,而且容易触发不必要的ViewHolder复用问题;notifyItemChanged()只刷新指定位置,性能更好,逻辑更精准。
  • 为什么要保存previousSelectedPos?
    点击新项时,必须把之前选中的项重置回正常样式,所以得先记录旧位置,再单独刷新它。
  • Java版本适配
    逻辑完全一致,只是语法调整:比如selectedPosition用int变量,Typeface.DEFAULT_BOLD同样适用,点击事件里的notifyItemChanged()调用方式相同。
额外优化建议
  • 可以把样式抽成XML中的style,比如定义text_selected和text_normal,然后在onBindViewHolder()里用holder.tvValue.setTextAppearance()切换,更便于统一维护。
  • 如果需要保留选中状态(比如屏幕旋转后不丢失),可以把selectedPosition存在ViewModel里,或者通过onSaveInstanceState()保存到Activity/Fragment的状态中。

这样就能完美解决你的问题了——点击新项时,之前的选中项会恢复正常,当前项变成加粗高亮,而且完全适配RecyclerView的复用机制!

内容的提问来源于stack exchange,提问作者nethra gowda

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:11:03