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

Android横向RecyclerView滚动触发多选及左边距异常问题求助

横向RecyclerView单选+复用错乱问题修复方案

问题根因

  • 没有适配RecyclerView的Holder复用机制:仅对position=0的条目设置了选中状态、左边距、不可点击属性,其他位置的条目复用曾经渲染过position=0的Holder时,会保留旧状态,导致出现间隔重复选中、多余左边距的问题
  • 选中状态存储在View层而非数据层:静态变量存储选中的View实例,View被回收复用后引用失效,滚动后选中状态逻辑混乱
  • 属性只赋值不重置:左边距、选中状态、文字颜色等属性仅在满足条件时修改,不满足时没有重置为默认值,复用后必然错乱

修复代码

首先在Adapter类中新增成员变量存储选中位置,删除原companion object中存储选中View的静态变量:

// 初始值为0,默认选中第一个条目
private var currentSelectedPos = 0

修改bind方法,所有属性按当前position状态全量赋值,避免复用错乱:

fun bind(
    context: Context?,
    name: String,
    position: Int
) {
    // 1. 统一处理左边距:仅第一个条目加左边距,其余条目重置为0
    val layoutParams = cardView?.layoutParams as ViewGroup.MarginLayoutParams?
    layoutParams?.leftMargin = if (position == 0) 52 else 0
    cardView?.layoutParams = layoutParams

    // 2. 统一处理选中状态、点击属性、文字颜色
    val isCurrentSelected = position == currentSelectedPos
    cardView?.apply {
        isSelected = isCurrentSelected
        isClickable = !isCurrentSelected
        findViewById<TextView>(R.id.iv_tab_name).setTextColor(
            ContextCompat.getColor(
                context!!,
                if (isCurrentSelected) R.color.black else R.color.setting_text
            )
        )
    }

    // 3. 点击事件逻辑
    itemView.setOnClickListener {
        // 已经是选中状态直接跳过
        if (position == currentSelectedPos) return@setOnClickListener
        // 更新选中位置,刷新新旧两个条目即可,不需要全量刷新
        val oldSelectedPos = currentSelectedPos
        currentSelectedPos = position
        notifyItemChanged(oldSelectedPos)
        notifyItemChanged(currentSelectedPos)
    }
}

onBindViewHolder逻辑不需要修改,保持原有调用即可。

修复说明

所有View属性都根据当前position的状态做全量赋值,不管Holder之前被用来渲染过什么位置的条目,每次绑定时都会被覆盖为正确状态,从根源上避免复用错乱。用数据层的位置变量存储选中状态,比存储易被回收的View实例更稳定,滚动后也能正确渲染选中效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 15:57:01