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

使用Jetpack Compose Navigation时,如何让顶部栏标题随页面切换更新?

实现Jetpack Compose Scaffold+Navigation的顶部栏/底部栏联动方案

核心思路

通过Navigation的页面栈状态监听,动态获取当前页面的配置信息(标题、是否属于主页面),实现顶部栏标题自动更新,同时控制底部栏仅在主页面显示、子页面隐藏。

步骤实现

1. 封装页面配置数据类

先定义统一的页面配置类,集中管理路由、标题和主页面标记:

data class Screen(
    val route: String,
    val title: String,
    val isMainScreen: Boolean = false // 标记是否为底部栏对应的主页面
)

// 全局页面配置
object AppScreens {
    val Home = Screen("home", "首页", isMainScreen = true)
    val Profile = Screen("profile", "我的", isMainScreen = true)
    val Settings = Screen("settings", "设置")
    val Detail = Screen("detail/{itemId}", "详情")
}

2. 配置NavHost与页面路由

在NavHost中注册所有页面,处理带参数的子页面路由:

@Composable
fun AppNavHost(navController: NavHostController) {
    NavHost(navController = navController, startDestination = AppScreens.Home.route) {
        composable(AppScreens.Home.route) {
            HomeScreen(navController)
        }
        composable(AppScreens.Profile.route) {
            ProfileScreen(navController)
        }
        composable(AppScreens.Settings.route) {
            SettingsScreen(navController)
        }
        composable(AppScreens.Detail.route) { backStackEntry ->
            val itemId = backStackEntry.arguments?.getString("itemId") ?: ""
            DetailScreen(itemId, navController)
        }
    }
}

3. Scaffold中联动顶部栏与底部栏

通过currentBackStackEntryAsState监听页面栈变化,动态更新顶部栏标题并控制底部栏显示:

@Composable
fun MainScreen() {
    val navController = rememberNavController()
    val backStackEntry by navController.currentBackStackEntryAsState()
    
    // 匹配当前路由对应的页面配置(兼容带参数的路由)
    val currentScreen = AppScreens.values().firstOrNull { screen ->
        backStackEntry?.destination?.route?.startsWith(screen.route.split("/")[0]) == true
    } ?: AppScreens.Home

    Scaffold(
        topBar = {
            TopAppBar(
                title = { Text(currentScreen.title) }
            )
        },
        bottomBar = {
            // 仅主页面显示底部栏
            if (currentScreen.isMainScreen) {
                BottomNavigation {
                    val currentRoute = backStackEntry?.destination?.route
                    AppScreens.values().filter { it.isMainScreen }.forEach { screen ->
                        BottomNavigationItem(
                            icon = { Icon(Icons.Default.Home, contentDescription = screen.title) },
                            label = { Text(screen.title) },
                            selected = currentRoute == screen.route,
                            onClick = {
                                navController.navigate(screen.route) {
                                    // 避免重复入栈,返回时恢复主页面状态
                                    popUpTo(navController.graph.startDestinationId) {
                                        saveState = true
                                    }
                                    launchSingleTop = true
                                    restoreState = true
                                }
                            }
                        )
                    }
                }
            }
        }
    ) { paddingValues ->
        AppNavHost(navController = navController)
    }
}

4. 子页面跳转示例

主页面跳转至子页面时,底部栏会自动隐藏:

@Composable
fun HomeScreen(navController: NavHostController) {
    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Button(onClick = { 
            navController.navigate(AppScreens.Detail.route.replace("{itemId}", "123")) 
        }) {
            Text("跳转到详情页")
        }
    }
}

关键细节

  • 路由匹配使用startsWith处理带参数的路由(如detail/{itemId}),确保能正确关联页面配置。
  • 底部栏跳转时的popUpTo和launchSingleTop配置,保证主页面在栈中唯一,返回逻辑更合理。
  • 页面配置集中管理,新增页面只需添加Screen实例,无需修改Scaffold核心逻辑,扩展性强。

内容的提问来源于stack exchange,提问作者user22376410

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 01:11:17