如何使用 Jetpack 导航组件修复 CollapsingToolbarLayout 不与 RecyclerView 折叠? (导航界面)
How to fix CollapsingToolbarLayout not collapsing with RecyclerView using the Jetpack Navigation Component? (NavigationUI)
-
android
-
android-layout
-
android-recyclerview
-
android-collapsingtoolbarlayout
-
android-jetpack-navigation
我正在使用新的 Jetpack 导航组件和 NavigationUI class 设置应用程序导航,以支持在 CollapsingToolbarLayout 中导航。
但是,使用 documentation.
中的 code/method 不起作用
我已经按照文档中所示设置了 MainActivity:
LinearLayout 作为父视图,在 AppBarLayout 中,在 CollapsingToolbarLayout 中,以及工具栏本身。和主机片段。
导航开始目的地是一个FrameLayout,其中包含实际的RecyclerView。
我尝试了各种 layout_scrollFlags 并尝试将 CoordinatorLayout 设置为父视图而不是 LinearLayout。
activity_main.xml
<LinearLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleGravity="top"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_collapseMode="pin"/>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph"/>
</LinearLayout>
在MainActivity的onCreate函数中:
// Set Toolbar as ActionBar
setSupportActionBar(findViewById(R.id.toolbar))
val layout = findViewById<CollapsingToolbarLayout>(R.id.collapsing_toolbar_layout)
val toolbar = findViewById<Toolbar>(R.id.toolbar)
val navController = findNavController(R.id.nav_host_fragment)
val appBarConfiguration = AppBarConfiguration(navController.graph)
layout.setupWithNavController(toolbar, navController, appBarConfiguration)
我预计崩溃行为的第一个目的地:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".restaurant.RestaurantsFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/restaurant_recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="@layout/restaurant_item"/>
</FrameLayout>
我预计在滚动 RecyclerView 时工具栏会折叠。
实际上它只是静态的。
我认为 RecyclerView 和 CollapsingToolbar 之间可能缺少联系?
我错过了什么?
找到解决方案。
使用 CoordinatorLayout 作为父视图而不是 LinearLayout。
删除 CollapsingToolbarLayout。
在工具栏中声明layout_scrollFlags(例如app:layout_scrollFlags="scroll|enterAlways|snap")。
并在片段视图中添加 app:layout_behavior="@string/appbar_scrolling_view_behavior"(这很重要,因为我们在主片段中使用了 RecyclerView)
main_activity.xml
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_scrollFlags="scroll|enterAlways|snap"
/>
</com.google.android.material.appbar.AppBarLayout>
<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
MainActivity onCreate
// Set Toolbar as ActionBar
setSupportActionBar(findViewById(R.id.toolbar))
val navController = findNavController(R.id.nav_host_fragment)
val appBarConfiguration = AppBarConfiguration(navController.graph)
findViewById<Toolbar>(R.id.toolbar)
.setupWithNavController(navController, appBarConfiguration)
谢谢你,你是我的救星。我最近也为此苦苦挣扎,所以我更多地尝试了您的解决方案,并且我来了一些
结论(撰写时间 2019-08-08):
TL;DR CollapsingToolbarLayout 也有效,但片段大小不正确。
- 顶层布局必须是 CoordinatorLayout,因为如果不是,则无法协调 AppBarLayout 和片段。
<fragment>
元素 必须 具有属性 app:layout_behavior="@string/appbar_scrolling_view_behavior"
。似乎 CoordinatorLayout 只在其直接子项中搜索以查找行为。
- 拥有
AppBarLayout
/CollapsingToolbarLayout
/Toolbar
层级实际上很好。只要 <fragment>
具有 app:layout_behavior
属性,这将
也很好用。
片段内的布局并不重要。在我的例子中使用视图模型,这意味着我需要一个额外的 <layout>
包装器,所以我已经尝试了两个
<layout>
<data></data>
<FrameLayout>
<RecyclerView/>
<FrameLayout>
</layout>
和
<layout>
<data></data>
<CoordinatorLayout>
<RecyclerView/>
<CoordinatorLayout>
</layout>
两者都可以正常工作。内部 CoordinatorLayout 不会吞下行为,因为 RecyclerView 没有或不使用行为,但这引出了我的下一点:
这种安排没有正确调整片段的大小。如果您还向片段添加了一个 FloatingActionButton,则它不能与 FrameLayout 一起正常工作(尽管 app:layout_anchorGravity="bottom|right|end"
仍位于左上角的 FAB)。
如果您在片段内使用 CoordinatorLayout,就像我在上面的第二个示例中那样,FAB 会跳转到正确的位置。显示和隐藏不起作用,即使您自己实现了 ScrollAwareFABBehavior。相反,FAB 滚动到屏幕外,显示片段是视口垂直高度的 100%,但向下移动了工具栏的高度(如果它是展开的 CollapsingToolbarLayout,这可能是 300dp 或几乎是屏幕的一半在我的例子中)。
我一直没能找到解决这个问题的办法,我打算暂时停止尝试。 single-activity/single-toolbar 模型似乎还不能处理 CoordinatorLayout 的事情。 Android 文档使用 LinearLayout 的原因可能是为了确保片段具有正确的垂直尺寸,但同时放弃任何动态行为特征。以后我可能会使用嵌套导航图,应用程序的每个部分都将包含相应的工具栏。
如果有人有任何建议或指点,请发表评论。我希望有一天能真正让这个工作。
android
android-layout
android-recyclerview
android-collapsingtoolbarlayout
android-jetpack-navigation
我正在使用新的 Jetpack 导航组件和 NavigationUI class 设置应用程序导航,以支持在 CollapsingToolbarLayout 中导航。 但是,使用 documentation.
中的 code/method 不起作用我已经按照文档中所示设置了 MainActivity: LinearLayout 作为父视图,在 AppBarLayout 中,在 CollapsingToolbarLayout 中,以及工具栏本身。和主机片段。
导航开始目的地是一个FrameLayout,其中包含实际的RecyclerView。
我尝试了各种 layout_scrollFlags 并尝试将 CoordinatorLayout 设置为父视图而不是 LinearLayout。
activity_main.xml
<LinearLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleGravity="top"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_collapseMode="pin"/>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph"/>
</LinearLayout>
在MainActivity的onCreate函数中:
// Set Toolbar as ActionBar
setSupportActionBar(findViewById(R.id.toolbar))
val layout = findViewById<CollapsingToolbarLayout>(R.id.collapsing_toolbar_layout)
val toolbar = findViewById<Toolbar>(R.id.toolbar)
val navController = findNavController(R.id.nav_host_fragment)
val appBarConfiguration = AppBarConfiguration(navController.graph)
layout.setupWithNavController(toolbar, navController, appBarConfiguration)
我预计崩溃行为的第一个目的地:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".restaurant.RestaurantsFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/restaurant_recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="@layout/restaurant_item"/>
</FrameLayout>
我预计在滚动 RecyclerView 时工具栏会折叠。 实际上它只是静态的。
我认为 RecyclerView 和 CollapsingToolbar 之间可能缺少联系? 我错过了什么?
找到解决方案。
使用 CoordinatorLayout 作为父视图而不是 LinearLayout。 删除 CollapsingToolbarLayout。 在工具栏中声明layout_scrollFlags(例如app:layout_scrollFlags="scroll|enterAlways|snap")。 并在片段视图中添加 app:layout_behavior="@string/appbar_scrolling_view_behavior"(这很重要,因为我们在主片段中使用了 RecyclerView)
main_activity.xml
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_scrollFlags="scroll|enterAlways|snap"
/>
</com.google.android.material.appbar.AppBarLayout>
<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
MainActivity onCreate
// Set Toolbar as ActionBar
setSupportActionBar(findViewById(R.id.toolbar))
val navController = findNavController(R.id.nav_host_fragment)
val appBarConfiguration = AppBarConfiguration(navController.graph)
findViewById<Toolbar>(R.id.toolbar)
.setupWithNavController(navController, appBarConfiguration)
谢谢你,你是我的救星。我最近也为此苦苦挣扎,所以我更多地尝试了您的解决方案,并且我来了一些 结论(撰写时间 2019-08-08):
TL;DR CollapsingToolbarLayout 也有效,但片段大小不正确。
- 顶层布局必须是 CoordinatorLayout,因为如果不是,则无法协调 AppBarLayout 和片段。
<fragment>
元素 必须 具有属性app:layout_behavior="@string/appbar_scrolling_view_behavior"
。似乎 CoordinatorLayout 只在其直接子项中搜索以查找行为。- 拥有
AppBarLayout
/CollapsingToolbarLayout
/Toolbar
层级实际上很好。只要<fragment>
具有app:layout_behavior
属性,这将 也很好用。 片段内的布局并不重要。在我的例子中使用视图模型,这意味着我需要一个额外的
<layout>
包装器,所以我已经尝试了两个<layout> <data></data> <FrameLayout> <RecyclerView/> <FrameLayout> </layout>
和
<layout> <data></data> <CoordinatorLayout> <RecyclerView/> <CoordinatorLayout> </layout>
两者都可以正常工作。内部 CoordinatorLayout 不会吞下行为,因为 RecyclerView 没有或不使用行为,但这引出了我的下一点:
这种安排没有正确调整片段的大小。如果您还向片段添加了一个 FloatingActionButton,则它不能与 FrameLayout 一起正常工作(尽管
app:layout_anchorGravity="bottom|right|end"
仍位于左上角的 FAB)。如果您在片段内使用 CoordinatorLayout,就像我在上面的第二个示例中那样,FAB 会跳转到正确的位置。显示和隐藏不起作用,即使您自己实现了 ScrollAwareFABBehavior。相反,FAB 滚动到屏幕外,显示片段是视口垂直高度的 100%,但向下移动了工具栏的高度(如果它是展开的 CollapsingToolbarLayout,这可能是 300dp 或几乎是屏幕的一半在我的例子中)。
我一直没能找到解决这个问题的办法,我打算暂时停止尝试。 single-activity/single-toolbar 模型似乎还不能处理 CoordinatorLayout 的事情。 Android 文档使用 LinearLayout 的原因可能是为了确保片段具有正确的垂直尺寸,但同时放弃任何动态行为特征。以后我可能会使用嵌套导航图,应用程序的每个部分都将包含相应的工具栏。
如果有人有任何建议或指点,请发表评论。我希望有一天能真正让这个工作。