使 AppBarLayout/CollapsingToolbarLayout 对 ViewPager 的 RecyclerView 中的滚动做出反应

Make AppBarLayout/CollapsingToolbarLayout react to scrolling in RecyclerView in ViewPager

我制作了一个带有 CollapsingToolbarLayout 和 ViewPager 的测试应用程序。 ViewPager 包含三个 Fragment,其中一个只是一个简单的 RecyclerView。我的问题是,当滚动 RecyclerView 时,CollapsingToolbarLayout(或更确切地说是 AppBarLayout)不会 expand/contract,除非布局未完全展开,RecyclerView 位于顶部,我向下滚动。然后 CollapsingToolbarLayout 也在展开。

注:我已经上传了测试申请here

我目前的布局如下:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true" >

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="256dp"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        android:fitsSystemWindows="true" >

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <ImageView
                android:id="@+id/mm_recipe_activity_image"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:src="@drawable/cake"
                android:scaleType="centerCrop"
                android:fitsSystemWindows="true"
                app:layout_collapseMode="pin"/>

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:layout_collapseMode="pin"/>

        </android.support.design.widget.CollapsingToolbarLayout>

    </android.support.design.widget.AppBarLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <android.support.design.widget.TabLayout
            android:id="@+id/tablayout"
            android:layout_width="match_parent"
            android:layout_height="48dp"
            app:tabMode="fixed"
            app:tabIndicatorHeight="0dp"
            />

        <android.support.v4.view.ViewPager
            android:id="@+id/viewpager"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </LinearLayout>


</android.support.design.widget.CoordinatorLayout>

ViewPager 中使用了两种类型的 Fragment,一种是包含大量文本的简单 TextView,另一种是 ViewPager。片段全部包裹在 NestedScrollView 中,以使 ViewPager 中的滚动与建议的布局的其余部分 和其他地方配合得很好。这是两个 Fragment 布局,第一个是简单的 TextView,

<android.support.v4.widget.NestedScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/pink">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/lorem"/>

    </LinearLayout>

</android.support.v4.widget.NestedScrollView>

然后是带有 RecyclerView 的那个:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true" >

    <android.support.v7.widget.RecyclerView
        android:id="@+id/yellow_recyclerview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/yellow" />

</android.support.v4.widget.NestedScrollView>

如何让 AppBarLayout/CollapsingToolbarLayout 对 RecyclerView 中的滚动做出反应?

这里有一些截图来说明我的意思:

从初始位置向上滚动会滚动 RecyclerView 本身,但不会滚动 AppBarLayout/CollapsingToolbarLayout。我现在想正常滚动 up/down 到 collapse/expand 它们。

在第一张图片中,CollapsingToolbarLayout 已折叠,RecyclerView 位于顶部。如果我在此时滚动 RecyclerView down,我将开始扩展 CollapsingToolbarLayout,这应该是预期的。但是,如果我中途停止并滚动 RecyclerView up,我仍然会向上滚动 RecyclerView,如第三张图所示。

奖金问题:上面第三张图片底部的灰色视图是什么?我看不到我已将其添加到任何地方。它在布局的底部也可见,只是一个普通的 TextView,所以不是因为 RecyclerView。

父布局的默认背景颜色。在 recyclerView/TextView/ViewPager 未覆盖整个屏幕之前,您将始终看到它。您将 wrap_content 作为两个元素的高度。尝试使它们 match_parent 并检查结果。

这里的问题是您不应该 "nest" 在 NestedScrollView 中使用 RecyclerView。

为什么?

因为 RecyclerView 自己实现了 'NestedScrollingChild' 和 'ScrollingView' 接口。 NestedScrollView 用于支持不具有滚动功能的视图,例如您在其他情况下成功实现的 LinearLayout。

确实,yellow_fragment.xml 更改为:

时会按预期工作
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView
    xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/yellow_recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/yellow"
        android:fillViewport="true"
    />

奖金答案:将 android:fillViewport="true" 添加到您的 RecyclerView 和 green_fragment.xml 和 pink_fragment.xml 中的 NestedScrollViews 将摆脱视图底部的灰色条带。你可能会问这是什么魔法:

当滚动视图中的子视图小于屏幕时,android:fillViewport="true" 是扩展该视图以填满屏幕的方法。查看其效果如下:

android:fillViewport = "true" _ vs "false" _

我删除了一段您的 TextView 文本以进一步突出差异。查看 Romain Guy 关于此功能的 blog post 以获取更多信息。

编辑:正如 Krøllebølle 在评论中提到的,确保拥有最新的支持库版本,因为这可能是灰色条纹在添加 [=11 后仍然存在的原因=] 在你看来。