You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:26:31