我正在构建一个应用程序,该应用程序使用ViewPager2
在所有具有垂直滚动内容RecyclerView
的页面上水平滚动,其中每个列表的第一位置都有一行带有水平滚动小部件的行,例如从下图可以看到,另一个附加到寻呼指示符类型小部件的RecyclerView
或ViewPager2
。
父级ViewPager2是CoordinatorLayout的子级,当RecyclerView垂直滚动时,该子级处理折叠顶部内容。然后,此ViewPager2会放大水平滚动的片段。因此,我们有parent layout
:
-- CoordinatorLayout
-- FrameLayout - has appbar scrolling behavior
-- ViewPager2
-- AppBarLayout
-- CollapsingToolbarLayout
-- ImageView - background
-- Toolbar
-- ConstraintLayout - Holds title and date
父级ViewPager2 child fragments' layout
:
-- FrameLayout
-- RecyclerView
-- Pager Indicator
内容RecyclerView的第一行具有相同的布局:
-- FrameLayout
-- RecyclerView
-- Pager Indicator
从上面的屏幕快照中可以看到,在第一次加载时,RecyclerView
与AppBarLayout
重叠,这是正确的行为。我在marginTop
的父级布局中添加了负数RecyclerView
,以实现此效果。我正在跟踪AppBarLayout.OnOffsetChangedListener
下的AppBarLayout偏移量变化,并且随着用户向上滚动,我正在减小或增大此负边距以使列表在AppBarLayout
下进行动画处理。
我面临的问题是,如果我从列表中的第一项开始垂直滚动,则不会触发AppBarLayout
来开始折叠其内容,因此内容会过早地在{{1}下出现}。请参见以下屏幕截图:
我希望AppBarLayout内容一开始就开始向上滚动
RecyclerView内容滚动,即使它是从第一个位置启动的。似乎第一项的AppBarLayout
并未提醒RecyclerView
开始崩溃。如果我从RecyclerView中的其他项目开始滚动,则观察到正确的行为。如果我从第一行拖动并按住,则还会观察到该错误。
我要实现的行为的一个很好的例子是Google新闻应用程序,其中有一个新闻栏目标签。以下是我的期望:
答案 0 :(得分:2)
结果证明很简单。如果您有嵌套的RecyclerView或类似的容器,则必须使用:
RecyclerView.setNestedScrollingEnabled(false)
答案 1 :(得分:0)
我通读了所提供的将 setNestedScrollingEnabled 设为 false 的答案,这对我来说很糟糕,因为它使 recyclerview 无法回收,并且如果您有一个庞大的列表,您可能会在内存中崩溃等等。所以我会给你一个算法,让它在不混淆 coordinatorLayout 的情况下工作。
在垂直回收视图上有一个滚动监听器,比如滚动监听器。无论何时滚动列表,您都会收到一个回调,表明它正在滚动。当它空闲时,你也应该得到回电。
现在当垂直回收视图被滚动时,水平列表上的 setNestedScrollingEnabled = false。
一旦垂直 recyclerview 空闲,则在水平列表上 setNestedScrollingEnabled = true。
还在xml中最初将水平recyclerview设置为setNestedScrollingEnabled = false
总结:本质上是在用户垂直滚动时关闭嵌套滚动。
当 coordinatorlayout 与不同方向的两个 recyclerviews 混淆时,这对 appbarlayout 非常有用。