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

Android嵌套RecyclerView使用及滚动颜色错乱问题解决

解决嵌套RecyclerView滚动时颜色错乱的问题

这个问题本质是RecyclerView的View复用机制导致的:外层商品Item被滚动复用后,内层颜色列表的选中状态没有和对应商品的绑定关系同步,出现状态错乱。以下是具体解决步骤:

1. 给商品数据绑定独立的选中状态

在你的商品数据类中添加一个字段,专门记录当前商品选中的颜色位置或ID,确保每个商品的颜色选中状态是独立存储的,而不是依赖ViewHolder的缓存。

示例数据类:

data class Product(
    val productId: String,
    val productName: String,
    val colorList: List<ColorItem>,
    var selectedColorPos: Int = 0 // 记录当前商品选中的颜色下标
)

data class ColorItem(val colorId: String, val colorName: String, val colorHex: String)

2. 优化外层商品Adapter的绑定逻辑

  • 不要在onBindViewHolder中每次都新建内层颜色Adapter,建议在创建外层ViewHolder时初始化内层Adapter,后续仅更新数据和选中状态,提升性能。
  • 绑定外层Item时,将当前商品的颜色列表和选中状态传递给内层Adapter,同时设置颜色选中的回调,当用户选中颜色时,更新对应商品的selectedColorPos字段,并刷新当前外层Item。

示例外层Adapter代码片段:

class ProductAdapter(private val productList: MutableList<Product>) : RecyclerView.Adapter<ProductAdapter.ProductViewHolder>() {

    inner class ProductViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val tvProductName: TextView = itemView.tv_product_name
        val rvColors: RecyclerView = itemView.rv_colors
        val colorAdapter = ColorAdapter() // 初始化内层Adapter,复用实例
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.item_product, parent, false)
        val holder = ProductViewHolder(view)
        // 给内层RecyclerView设置布局管理器
        holder.rvColors.layoutManager = LinearLayoutManager(parent.context, LinearLayoutManager.HORIZONTAL, false)
        holder.rvColors.adapter = holder.colorAdapter
        // 禁用内层嵌套滚动,避免滑动冲突和复用问题
        holder.rvColors.isNestedScrollingEnabled = false
        return holder
    }

    override fun onBindViewHolder(holder: ProductViewHolder, position: Int) {
        val currentProduct = productList[position]
        holder.tvProductName.text = currentProduct.productName

        // 更新内层颜色Adapter的数据和选中状态
        holder.colorAdapter.updateData(currentProduct.colorList, currentProduct.selectedColorPos)
        // 设置颜色选中回调
        holder.colorAdapter.onColorSelected = { selectedPos ->
            // 更新当前商品的选中状态
            currentProduct.selectedColorPos = selectedPos
            // 仅刷新当前外层Item,避免全量刷新影响性能
            notifyItemChanged(position)
        }
    }

    override fun getItemCount() = productList.size
}

3. 优化内层颜色Adapter的状态刷新逻辑

在内层颜色Adapter的onBindViewHolder中,严格根据传递过来的选中状态来设置颜色Item的样式,不要依赖ViewHolder的缓存状态。同时处理点击事件时,通过回调通知外层更新对应商品的状态。

示例内层颜色Adapter代码片段:

class ColorAdapter : RecyclerView.Adapter<ColorAdapter.ColorViewHolder>() {
    private var colorItems = emptyList<ColorItem>()
    private var selectedPosition = 0
    var onColorSelected: ((Int) -> Unit)? = null

    fun updateData(colors: List<ColorItem>, selectedPos: Int) {
        this.colorItems = colors
        this.selectedPosition = selectedPos
        notifyDataSetChanged()
    }

    inner class ColorViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val tvColorName: TextView = itemView.tv_color_name
        val colorIndicator: View = itemView.view_color_indicator
    }

    override fun onBindViewHolder(holder: ColorViewHolder, position: Int) {
        val color = colorItems[position]
        holder.tvColorName.text = color.colorName
        holder.colorIndicator.setBackgroundColor(Color.parseColor(color.colorHex))

        // 根据选中状态设置Item样式
        if (position == selectedPosition) {
            holder.itemView.setBackgroundResource(R.drawable.bg_color_selected)
            holder.tvColorName.setTextColor(Color.WHITE)
        } else {
            holder.itemView.setBackgroundResource(R.drawable.bg_color_normal)
            holder.tvColorName.setTextColor(Color.BLACK)
        }

        // 处理颜色选中事件
        holder.itemView.setOnClickListener {
            onColorSelected?.invoke(position)
        }
    }

    override fun getItemCount() = colorItems.size
}

4. 禁用内层RecyclerView的嵌套滚动(推荐)

给内层RecyclerView添加android:nestedScrollingEnabled="false"属性,让内层列表跟随外层一起滚动,既可以避免滑动冲突,也能减少不必要的View复用触发,提升整体稳定性。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 00:42:38