使 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 后仍然存在的原因=] 在你看来。
我制作了一个带有 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 中的滚动与建议的布局的其余部分
<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"
我删除了一段您的 TextView 文本以进一步突出差异。查看 Romain Guy 关于此功能的 blog post 以获取更多信息。
编辑:正如 Krøllebølle 在评论中提到的,确保拥有最新的支持库版本,因为这可能是灰色条纹在添加 [=11 后仍然存在的原因=] 在你看来。