如何实现Android多TabLayout滚动时依次吸顶且可正常交互的效果
2021年12月13日更新
我当前的布局代码如下:
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <data /> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/background_color"> <!-- 头部布局 --> <include android:id="@+id/layout_header" layout="@layout/layout_header" /> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent"> <WebView android:id="@+id/wvChart" android:layout_width="match_parent" android:layout_height="@dimen/webview_height" /> <com.google.android.material.tabs.TabLayout android:id="@+id/tl1" android:layout_width="match_parent" android:layout_height="@dimen/tablayout_height" style="@style/TabLayoutStyle" app:layout_constraintTop_toBottomOf="@id/wvChart" app:tabTextAppearance="@style/TabLayoutTextStyle"/> <androidx.viewpager2.widget.ViewPager2 android:id="@+id/vpg1" android:minHeight="@dimen/viewpager_market_info" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/background_color" app:layout_constraintTop_toBottomOf="@id/tl1"/> <com.google.android.material.tabs.TabLayout android:id="@+id/tl2" android:layout_width="match_parent" android:layout_height="@dimen/tablayout_height" style="@style/TabLayoutStyle" app:layout_constraintTop_toBottomOf="@id/vpg1" app:tabTextAppearance="@style/TabLayoutTextStyle"/> <androidx.viewpager2.widget.ViewPager2 android:id="@+id/vpg2" android:minHeight="@dimen/viewpager_market_info" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/background_color" app:layout_constraintTop_toBottomOf="@id/tl2"/> </androidx.constraintlayout.widget.ConstraintLayout> </LinearLayout> </layout>
我目前在使用第三方StickyScrollView开源库实现,基本符合预期但存在少量bug,还是希望找到其他更稳定的实现方案,谢谢。
解决方案
推荐使用Google官方原生的CoordinatorLayout + AppBarLayout联动方案实现,无需引入第三方库,稳定性和交互性都有保障,完全匹配你的需求。
核心实现思路
- 替换根布局为
CoordinatorLayout,这是官方专门用来实现滚动联动效果的标准容器。 - 将所有需要跟随滚动的头部内容(顶部自定义header、WebView、tl1、vpg1、tl2)全部放入
AppBarLayout容器内,给每个子项配置对应的滚动属性:- 不需要吸顶的普通滚动内容(顶部header、WebView、vpg1)添加属性
app:layout_scrollFlags="scroll|enterAlways" - 需要吸顶的TabLayout(tl1、tl2)添加属性
app:layout_scrollFlags="scroll|enterAlways|snap",snap属性可以让Tab滚动到边界时自动吸附,不会出现半隐藏的状态
- 不需要吸顶的普通滚动内容(顶部header、WebView、vpg1)添加属性
- 将最底部的vpg2放入
NestedScrollView中,给NestedScrollView添加app:layout_behavior="@string/appbar_scrolling_view_behavior"属性,建立和AppBarLayout的滚动联动关系。
注意事项
- 给vpg1和vpg2都设置
isNestedScrollingEnabled = false,关闭ViewPager2的默认嵌套滚动逻辑,避免和父布局的滚动逻辑冲突。 - 如果vpg1的子页面高度不固定,需要自定义ViewPager2的测量逻辑,重写onMeasure方法让其可以正确适配所有子页面的高度,避免内容显示不全。
- 如果你的vpg2内部是列表类布局,也可以直接用RecyclerView替代NestedScrollView,同样添加滚动behavior即可。
如果你的业务场景全是列表项构成,也可以选择用RecyclerView的StickyHeaderItemDecoration实现多吸顶效果,给每个Tab对应的分组配置吸顶属性即可,这种方案适合纯列表的多吸顶场景,性能表现也很优秀。
内容的提问来源于stack exchange,提问作者Harry T.
相关产品推荐
相关产品推荐

