Jetpack Navigation适配不同Toolbar:折叠式Toolbar集成咨询
当然可以把折叠式Toolbar集成到单Activity+Jetpack Navigation的架构里,完全不需要单独用一个Activity!我给你分享几个实用的实现方案:
方案1:监听导航目的地,动态切换Toolbar布局
这种方法的核心是在单Activity的布局中同时包含普通Toolbar和折叠式Toolbar的结构,默认隐藏折叠版,当导航到目标Fragment时切换显示状态,并配置对应的Toolbar行为。
第一步:编写Activity的布局文件
在你的主Activity布局里,用CoordinatorLayout包裹两种Toolbar结构和导航容器:
<androidx.coordinatorlayout.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"> <!-- 折叠式Toolbar区域 --> <com.google.android.material.appbar.AppBarLayout android:id="@+id/collapsing_app_bar" android:layout_width="match_parent" android:layout_height="wrap_content" android:visibility="gone"> <com.google.android.material.appbar.CollapsingToolbarLayout android:id="@+id/collapsing_toolbar" android:layout_width="match_parent" android:layout_height="250dp" app:layout_scrollFlags="scroll|exitUntilCollapsed"> <!-- 折叠区域的自定义内容,比如背景图 --> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerCrop" android:src="@drawable/header_bg" app:layout_collapseMode="parallax"/> <androidx.appcompat.widget.Toolbar android:id="@+id/collapsing_toolbar_view" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:layout_collapseMode="pin"/> </com.google.android.material.appbar.CollapsingToolbarLayout> </com.google.android.material.appbar.AppBarLayout> <!-- 普通Toolbar区域 --> <com.google.android.material.appbar.AppBarLayout android:id="@+id/normal_app_bar" android:layout_width="match_parent" android:layout_height="wrap_content"> <androidx.appcompat.widget.Toolbar android:id="@+id/normal_toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize"/> </com.google.android.material.appbar.AppBarLayout> <!-- 导航容器 --> <androidx.fragment.app.FragmentContainerView 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>
第二步:在Activity中监听导航变化
通过NavController的目的地监听器,切换两种Toolbar的可见性,并配置对应的ActionBar:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val navController = findNavController(R.id.nav_host_fragment) // 监听导航目的地变化 navController.addOnDestinationChangedListener { _, destination, _ -> when (destination.id) { // 匹配需要折叠Toolbar的Fragment ID R.id.collapsing_content_fragment -> { normal_app_bar.visibility = View.GONE collapsing_app_bar.visibility = View.VISIBLE // 设置折叠Toolbar为ActionBar setSupportActionBar(collapsing_toolbar_view) // 配置折叠Toolbar的标题等属性 collapsing_toolbar.title = destination.label // 确保首次进入时展开状态 collapsing_app_bar.setExpanded(true, true) } else -> { // 恢复普通Toolbar模式 collapsing_app_bar.visibility = View.GONE normal_app_bar.visibility = View.VISIBLE setSupportActionBar(normal_toolbar) supportActionBar?.title = destination.label } } // 同步导航返回按钮 NavigationUI.setupActionBarWithNavController(this, navController) } } override fun onSupportNavigateUp(): Boolean { val navController = findNavController(R.id.nav_host_fragment) return navController.navigateUp() || super.onSupportNavigateUp() }
第三步:配置目标Fragment的滚动行为
在需要折叠Toolbar的Fragment布局中,确保根布局是支持滚动的容器(比如NestedScrollView或RecyclerView),并设置滚动行为:
<androidx.core.widget.NestedScrollView 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" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <!-- Fragment的内容布局 --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="16dp"> <!-- 具体内容 --> </LinearLayout> </androidx.core.widget.NestedScrollView>
方案2:让Fragment自主配置Toolbar(更灵活)
如果需要更精细化的控制,可以定义一个接口,让每个Fragment自主决定需要哪种Toolbar样式,Activity只负责执行配置逻辑。
第一步:定义Toolbar配置接口
interface ToolbarConfigurable { fun configureToolbar(activity: MainActivity) }
第二步:在目标Fragment中实现接口
class CollapsingContentFragment : Fragment(), ToolbarConfigurable { override fun configureToolbar(activity: MainActivity) { activity.apply { // 切换到折叠Toolbar模式 normal_app_bar.visibility = View.GONE collapsing_app_bar.visibility = View.VISIBLE setSupportActionBar(collapsing_toolbar_view) collapsing_toolbar.title = "我的折叠页面" // 自定义菜单项(比如添加分享按钮) collapsing_toolbar_view.menu.clear() collapsing_toolbar_view.inflateMenu(R.menu.menu_collapsing) } } // 其他Fragment逻辑... }
第三步:在Activity中调用Fragment的配置
navController.addOnDestinationChangedListener { _, _, _ -> // 获取当前显示的Fragment val currentFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) ?.childFragmentManager?.fragments?.firstOrNull() if (currentFragment is ToolbarConfigurable) { // 让Fragment自主配置Toolbar currentFragment.configureToolbar(this) } else { // 默认使用普通Toolbar collapsing_app_bar.visibility = View.GONE normal_app_bar.visibility = View.VISIBLE setSupportActionBar(normal_toolbar) supportActionBar?.title = "默认标题" normal_toolbar.menu.clear() } NavigationUI.setupActionBarWithNavController(this, navController) }
总结
这两种方案都能完美解决你的问题,不需要单独为折叠Toolbar保留Activity。方案1适合简单的场景,方案2更适合需要每个Fragment自定义Toolbar样式的复杂场景。
内容的提问来源于stack exchange,提问作者MichaelThePotato
相关产品推荐
相关产品推荐

