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

RecyclerView Adapter滚动时重复添加TextView问题求助

解决RecyclerView滚动后标签重复显示的问题

嘿,这个问题我太熟了!核心原因就是RecyclerView的ViewHolder复用机制在搞事情,咱们一步步来搞定它:

问题根源

当RecyclerView滚动时,滑出屏幕的ViewHolder会被回收,重新分配给刚进入屏幕的新item。如果你的Adapter在onBindViewHolder方法里,每次都直接往标签容器(比如LinearLayout)里添加新的TextView标签,但没有先清空容器里之前的内容,那复用的时候旧标签就会保留,新标签又叠加上,自然就出现了滚动一次多一组标签的情况。

快速解决方案:绑定前清空容器

这是最直接的修复方式,在绑定当前item的数据之前,先把标签容器里的所有子View清除干净,再添加当前item的标签。

假设你的ViewHolder里有一个LinearLayout用来装标签,代码示例如下:

class VideoAdapter(private val _c: Context, private val dataList: List<VideoItem>) : RecyclerView.Adapter<VideoAdapter.ViewHolder>() {

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val tagContainer: LinearLayout = itemView.findViewById(R.id.tag_container)
        // 其他控件...
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        // 关键步骤:先清空标签容器,避免复用旧标签
        holder.tagContainer.removeAllViews()

        // 处理当前item的标签数据
        val currentItem = dataList[position]
        currentItem.tags.forEach { tagText ->
            val tagTv = TextView(_c).apply {
                text = tagText
                // 设置标签的样式(背景、内边距等)
                setBackgroundResource(R.drawable.tag_background)
                setPadding(dp2px(8), dp2px(4), dp2px(8), dp2px(4))
                layoutParams = LinearLayout.LayoutParams(
                    LinearLayout.LayoutParams.WRAP_CONTENT,
                    LinearLayout.LayoutParams.WRAP_CONTENT
                ).apply {
                    marginEnd = dp2px(4)
                }
            }
            holder.tagContainer.addView(tagTv)
        }

        // 其他绑定逻辑...
    }

    // 辅助方法:dp转px
    private fun dp2px(dp: Int): Int {
        return (_c.resources.displayMetrics.density * dp).toInt()
    }

    // 其他必要方法(onCreateViewHolder、getItemCount)...
}

进阶优化:复用标签控件(提升性能)

如果你的标签数量有上限(比如最多显示3个),可以在ViewHolder初始化时预先创建好标签TextView,绑定数据时只更新内容和显示状态,避免频繁创建和销毁View,提升滚动流畅度:

inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    val tagContainer: LinearLayout = itemView.findViewById(R.id.tag_container)
    // 预先创建最多3个标签控件
    private val tagViews = mutableListOf<TextView>()

    init {
        repeat(3) {
            val tagTv = TextView(itemView.context).apply {
                setBackgroundResource(R.drawable.tag_background)
                setPadding(dp2px(8), dp2px(4), dp2px(8), dp2px(4))
                layoutParams = LinearLayout.LayoutParams(
                    LinearLayout.LayoutParams.WRAP_CONTENT,
                    LinearLayout.LayoutParams.WRAP_CONTENT
                ).apply {
                    marginEnd = dp2px(4)
                }
                visibility = View.GONE // 默认隐藏
            }
            tagViews.add(tagTv)
            tagContainer.addView(tagTv)
        }
    }

    // 对外提供绑定标签的方法
    fun bindTags(tags: List<String>) {
        // 先隐藏所有标签
        tagViews.forEach { it.visibility = View.GONE }
        // 给需要显示的标签设置内容并显示
        tags.forEachIndexed { index, tagText ->
            if (index < tagViews.size) {
                tagViews[index].apply {
                    text = tagText
                    visibility = View.VISIBLE
                }
            }
        }
    }
}

// 在onBindViewHolder里调用:
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    val currentItem = dataList[position]
    holder.bindTags(currentItem.tags)
    // 其他绑定逻辑...
}

重要注意事项

  • 永远记住:ViewHolder是复用的,所有随item变化的内容(比如标签、图片、选中状态、文本内容等),在绑定数据时都要做重置或更新处理,不能依赖ViewHolder的初始状态。
  • 如果是用动态添加View的方式展示可变内容,一定要先清空容器再添加新内容,否则旧内容会残留导致重复显示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:56:40