嵌套ViewPager2场景下AppBar慢滑动不跟随折叠问题求解
可行解决步骤:
修正
fragment_challenge_post.xml的错误配置- 删除根布局ConstraintLayout上的
app:layout_behavior="@string/appbar_scrolling_view_behavior"属性,该属性仅对CoordinatorLayout的直接子View生效,加在fragment根布局上无意义还会干扰滚动事件分发 - 将RecyclerView的
android:layout_height="wrap_content"改为android:layout_height="match_parent",wrap_content会导致RecyclerView一次性测量所有子项失去滚动特性,慢拖时事件被错误消费无法联动AppBar,快滑时惯性事件能透传才表现正常,完全匹配你遇到的问题特征 - 给RecyclerView增加
android:nestedScrollingEnabled="true"属性,确保嵌套滚动能力正常开启
- 删除根布局ConstraintLayout上的
调整SwipeRefreshLayout的触发规则
你当前把SwipeRefreshLayout放在最外层包裹整个CoordinatorLayout,垂直滚动事件很容易被它提前拦截处理下拉刷新逻辑,切断AppBarLayout的滚动联动。两个可选方案:- 将SwipeRefreshLayout挪到fragment中,仅包裹RecyclerView
- 保留现有层级的话,给AppBarLayout加偏移监听,仅当AppBar完全展开且RecyclerView滚动到顶部时才允许下拉刷新:
app_bar.addOnOffsetChangedListener { _, offset -> swipeRefresh.isEnabled = offset == 0 && !challengePostRecyclerView.canScrollVertically(-1) }优化NestedScrollableHost的事件拦截逻辑
官方默认的NestedScrollableHost仅处理了水平/垂直滚动的基础冲突,没有适配CoordinatorLayout的嵌套滚动场景,需要修改onInterceptTouchEvent逻辑,垂直滚动时主动把事件交给外层处理:private var downX = 0f private var downY = 0f private val touchSlop by lazy { ViewConfiguration.get(context).scaledTouchSlop } override fun onInterceptTouchEvent(e: MotionEvent): Boolean { when (e.action) { MotionEvent.ACTION_DOWN -> { downX = e.x downY = e.y parent.requestDisallowInterceptTouchEvent(true) } MotionEvent.ACTION_MOVE -> { val dx = e.x - downX val dy = e.y - downY if (abs(dy) > abs(dx) && abs(dy) > touchSlop) { // 垂直滚动,交还给外层AppBar联动逻辑处理 parent.requestDisallowInterceptTouchEvent(false) } else if (abs(dx) > touchSlop) { // 水平滚动,交给内部ViewPager2处理 parent.requestDisallowInterceptTouchEvent(true) } } } return super.onInterceptTouchEvent(e) }额外检查:给外层
challengeDetailsViewPager设置合理的offscreenPageLimit,避免fragment频繁重建导致滚动状态异常。
内容的提问来源于stack exchange,提问作者Ankur Gupta
相关产品推荐
相关产品推荐

