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
相关产品推荐
相关产品推荐

