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

NestedScrollView内容变更后自动滚动到顶部,如何保持原有滚动高度?

问题根因

你遇到的滚动回弹问题,本质是筛选后RecyclerView更新数据触发全局重布局,NestedScrollView会自动调整滚动位置到默认聚焦的子View,最终滚动到页面顶部。

解决方案

下面按优先级从高到低给出可行方案:

方案1:修改布局属性(优先选用,无需额外代码)

在你现有布局的RecyclerView节点中补充以下属性即可:

<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/list"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="24dp"
    android:focusable="false"
    android:focusableInTouchMode="false"
    android:nestedScrollingEnabled="false"
    android:isScrollContainer="false"
    app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />

说明:

  • 禁用RecyclerView的焦点获取能力,避免NestedScrollView滚动到RecyclerView位置
  • 禁用嵌套滚动,避免ScrollView和RecyclerView的滚动事件冲突
  • 明确指定layoutManager,减少重布局时的测量计算

方案2:手动记录恢复滚动位置

如果修改布局后仍有问题,可以在筛选逻辑中手动保存和恢复滚动位置:

Kotlin 示例代码

// 点击筛选按钮时先记录当前滚动偏移
val currentScrollY = nested_scrollView.scrollY
// 执行你的筛选逻辑,更新Adapter数据集
adapter.setNewData(filteredList)
// 等待布局重绘完成后恢复滚动位置
nested_scrollView.post {
    nested_scrollView.scrollTo(0, currentScrollY)
}

Java 示例代码

// 记录滚动位置
int currentScrollY = nestedScrollView.getScrollY();
// 执行筛选、更新Adapter
adapter.setNewData(filteredList);
// 恢复滚动位置
nestedScrollView.post(() -> nestedScrollView.scrollTo(0, currentScrollY));

方案3:使用DiffUtil局部更新列表

替换原有全局调用notifyDataSetChanged()的更新方式,改用DiffUtil计算新旧数据集差异,仅局部更新变化的条目,不会触发整个页面重布局,从根源避免滚动跳转,同时大幅提升列表更新性能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 10:15:03