带有 CollapsingToolbarLayout 的垂直 Recyclerview 中的水平滚动 Recyclerview

Horizontal Scroll Recyclerview in Vertical Recyclerview with CollapsingToolbarLayout

我正在构建一个应用程序,它使用 ViewPager2 水平滚动跨页面,每个页面都有垂直滚动的内容 RecyclerView 其中每个列表的第一个位置有一行带有水平滚动小部件例如另一个 RecyclerViewViewPager2 附加到 Pager Indicator 类型的小部件,如下图所示。

父级 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 

您可以从上面的屏幕截图中看到,在第一次加载时 RecyclerViewAppBarLayout 重叠,这是正确的行为。我在 RecyclerView 的父布局中添加了负值 marginTop 来实现这种效果。我正在使用 AppBarLayout.OnOffsetChangedListener 跟踪 AppBarLayout 偏移量变化,并且当用户向上滚动时,我正在减少或增加此负边距以使列表在 AppBarLayout 下具有动画效果。

我面临的问题是,如果我从列表中的第一项开始垂直滚动,那么 AppBarLayout 不会被触发开始折叠其内容,因此内容会过早地结束在 AppBarLayout。请参阅以下屏幕截图:

我希望 AppBarLayout 内容在我启动 内容 RecyclerView 滚动,即使它是从第一个位置启动的。似乎第一项的 RecyclerView 没有提醒 AppBarLayout 开始折叠。如果我从 RecyclerView 中的其他项目开始滚动,则会观察到正确的行为。如果我从第一行向上拖动并按住,那么也会观察到错误。

我试图实现的行为的一个很好的例子是 Google 新闻应用程序,其中有一个新闻栏目选项卡。以下是我所期待的:

事实证明解决方案很简单。如果你有一个嵌套的 RecyclerView 或类似的容器,那么你必须使用:

RecyclerView.setNestedScrollingEnabled(false)

我通读了提供的使用 setNestedScrollingEnabled 为 false 的答案,这对我来说很糟糕,因为它使 recyclerview 无法回收,如果你有一个巨大的列表,你可能会在内存中崩溃等。所以我会给你一个算法,让它工作而不混淆 coordinatorLayout。

  1. 垂直recyclerview上有滚动监听器,比如滚动监听器。每当滚动列表时,您都会收到一个回调,表明它正在 滚动 。您还应该在 空闲 .

    时收到回电
  2. 现在,当垂直 recylerview 正在滚动 时,水平列表上的 setNestedScrollingEnabled = false。

  3. 一旦垂直 Recyclerview 空闲,水平列表上的 setNestedScrollingEnabled = true。

  4. 最初还在xml

    中将水平recyclerview设置为setNestedScrollingEnabled = false

总结:本质上是在用户垂直滚动时关闭嵌套滚动。

当 coordinatorlayout 与两个不同方向的 recyclerviews 混淆时,这对 appbarlayout 非常有用。