Android ScrollView嵌套RecyclerView滚动时界面闪烁怎么解决?
问题原因分析
- 滚动逻辑错误:RecyclerView滚动回调的
dy是单次滚动的增量值,你直接用该值设置ScrollView的绝对滚动位置scrollY,没有做偏移量累加,滚动位置计算完全错误 - 嵌套滚动冲突:ScrollView和RecyclerView均为可滚动容器,未配置嵌套滚动规则时会同时消费触摸事件,慢速滑动时系统事件分发在两个控件间来回切换,就会出现上下抖动
- 布局参数不匹配:头部高度为100dp,你给RecyclerView外层布局设置了150dp的顶部边距,滚动阈值
headerHeight和实际可滚动偏移量不匹配,进一步放大了滚动异常
最优修复方案(推荐)
用官方嵌套滚动组件CoordinatorLayout+AppBarLayout实现头部折叠效果,官方已经处理了所有滚动冲突,不需要自己写滚动监听:
<androidx.coordinatorlayout.widget.CoordinatorLayout android:layout_width="match_parent" android:layout_height="match_parent"> <com.google.android.material.appbar.AppBarLayout android:id="@+id/appBar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@android:color/transparent"> <!-- 头部布局 --> <RelativeLayout android:id="@+id/header" android:layout_width="match_parent" android:layout_height="100dp" app:layout_scrollFlags="scroll|enterAlways"/> </com.google.android.material.appbar.AppBarLayout> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" android:layout_marginTop="50dp"/> </androidx.coordinatorlayout.widget.CoordinatorLayout>
只需要上述布局就可以实现跟随RecyclerView滚动自动隐藏/显示头部的效果,完全没有抖动问题。
兼容现有ScrollView布局的修复方案
如果要保留现有结构,按以下步骤修改:
- 先给RecyclerView关闭嵌套滚动,避免和ScrollView抢事件
recyclerView.setNestedScrollingEnabled(false);
- 修正滚动逻辑,用累加的偏移量控制ScrollView滚动,不要直接用单次增量设置绝对位置
// 类内声明成员变量 private int totalScrollOffset = 0; @Override public void onScroll(int dy) { // 累加滚动偏移,限制范围在0到头部高度之间 totalScrollOffset = Math.max(0, Math.min(totalScrollOffset + dy, headerHeight)); scrollView.scrollTo(0, totalScrollOffset); }
- 调整布局参数,把RecyclerView外层RelativeLayout的
android:layout_marginTop="150dp"改为android:layout_marginTop="100dp",和头部高度对齐,避免出现空白间隙。
内容的提问来源于stack exchange,提问作者stavros.3p
相关产品推荐
相关产品推荐

