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

NestedScrollView内嵌RecyclerView无法滚动到指定item问题求助

问题修复方案

根本原因

你当前计算滚动目标值的坐标体系错误:view.y获取的是RecyclerView子item相对于它的直接父控件(RecyclerView本身)的y轴偏移量,而NestedScrollView的smoothScrollTo方法要求传入的是目标点相对于NestedScrollView直接子布局(即XML中包裹RecyclerView的垂直LinearLayout)的偏移量。你没有把RecyclerView自身在父布局里的偏移量算入目标值,位置越靠后的item计算出来的目标值误差越大,超出ScrollView的可滚动范围后就会直接滚动到底部,只有前几个在可见区域的item因为误差小可以正常滚动。

修复后代码

private fun scrollToPosition(position: Int) {
    if (position !in 0 until variantsAdapter.itemCount) return

    val targetItem = binding.variantsRecyclerView.findViewWithTag<ConstraintLayout>("pos_$position")
    // 目标item还未被RecyclerView渲染时,先让RecyclerView滚动到对应位置触发渲染,再递归调用滚动逻辑
    if (targetItem == null) {
        binding.variantsRecyclerView.scrollToPosition(position)
        binding.variantsRecyclerView.post { scrollToPosition(position) }
        return
    }

    // 计算目标item在窗口中的绝对坐标
    val itemLocation = IntArray(2)
    targetItem.getLocationInWindow(itemLocation)
    // 计算NestedScrollView直接子布局在窗口中的绝对坐标
    val scrollChildLocation = IntArray(2)
    binding.nestedScrollView.getChildAt(0).getLocationInWindow(scrollChildLocation)
    
    // 计算相对于滚动容器的目标偏移量,避免滚动到负值超出顶部
    val targetScrollY = (itemLocation[1] - scrollChildLocation[1]).coerceAtLeast(0)

    binding.nestedScrollView.post {
        binding.nestedScrollView.smoothScrollTo(0, targetScrollY)
        targetItem.requestFocus()
    }
}

优化说明

  • 去掉了硬编码的200ms延迟,改用post方法保证代码在View布局刷新完成后再执行,适配不同性能的设备,避免固定延迟带来的时序问题
  • 新增了目标item未渲染的兼容逻辑,即使是非常靠后的未加载item也能正常触发滚动
  • 增加了滚动边界判断,避免出现向上滚动超出顶部的异常情况

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 15:24:03