Android基于Voyager导航实现不同TopAppBar+统一BottomAppBar
在Android应用中使用Voyager实现差异化TopAppBar与全局统一BottomAppBar
需求说明
- 不同页面展示对应自定义的TopAppBar(示例:首页标题为“home”,设置页标题为“settings”)
- 全局保持BottomAppBar样式一致
基础实现代码
主布局MainCompose
@Composable fun MainCompose(){ AppTheme { Navigator(ProjectScreen()) {navigation -> Scaffold( bottomBar = { BottomNavigationBar() }, ){innerPadding -> SlideTransition( navigator = navigation, modifier = Modifier.padding(innerPadding) ) } } } }
全局BottomAppBar实现
@Composable fun BottomNavigationBar() { val navigator = LocalNavigator.currentOrThrow BottomAppBar( actions = { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly ) { allScreens.forEach { navLinks -> TextButton(onClick = { navigator.push(navLinks.screen) }) { Column( horizontalAlignment = Alignment.CenterHorizontally ) { Row { navLinks.icon() } Spacer(Modifier.padding(4.dp)) Row { Text(navLinks.name, style = MaterialTheme.typography.labelMedium) } } } } } } ) }
可行解决方案实现
修改后的主布局MainCompose
通过监听导航栈当前活跃页面,动态渲染对应TopAppBar:
@Composable fun MainCompose(){ AppTheme { Navigator(ProjectScreen()) {navigation -> val currentScreen = navigation.lastItem Scaffold( bottomBar = { BottomNavigationBar() }, topBar = { TopBarForCurrentScreen(currentScreen ,navigation) } ){innerPadding -> SlideTransition( navigator = navigation, modifier = Modifier.padding(innerPadding) ) } } } }
页面差异化TopAppBar实现
根据当前页面类型,返回对应定制化的TopAppBar:
@OptIn(ExperimentalMaterial3Api::class) @Composable fun TopBarForCurrentScreen(currentScreen: Screen ,navigation: Navigator) { when (currentScreen) { is ProjectScreen -> { TopAppBar( navigationIcon = { Icon( painter = painterResource(R.drawable.project), contentDescription = "icon", Modifier.size(20.dp) ) }, title = { Text( "Projects", style = MaterialTheme.typography.titleLarge, fontWeight = FontWeight.Bold ) }, colors = TopAppBarDefaults.topAppBarColors( containerColor = MaterialTheme.colorScheme.secondaryContainer, titleContentColor = MaterialTheme.colorScheme.onSecondaryContainer ), actions = { IconButton(onClick = {}) { Icon(Icons.Filled.Search, contentDescription = "search") } Button ( onClick = { navigation.push(FormScreen()) }, colors = ButtonDefaults.buttonColors( containerColor = MaterialTheme.colorScheme.tertiaryContainer, contentColor = MaterialTheme.colorScheme.onTertiaryContainer ) ) { Row( horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically ) { Column { Icon( Icons.Filled.Add, contentDescription = "Create" ) } Column { Text("Create") } } } } ) } is FormScreen -> { TopAppBar( navigationIcon = { Icon( painter = painterResource(R.drawable.form), contentDescription = "icon", Modifier.size(20.dp) ) }, title = { Text( "Forms", style = MaterialTheme.typography.titleLarge, fontWeight = FontWeight.Bold ) }, colors = TopAppBarDefaults.topAppBarColors( containerColor = MaterialTheme.colorScheme.secondaryContainer, titleContentColor = MaterialTheme.colorScheme.onSecondaryContainer ), ) } else -> { TopAppBar( navigationIcon = { Icon( painter = painterResource(R.drawable.project), contentDescription = "icon", Modifier.size(20.dp) ) }, title = { Text( "Projects", style = MaterialTheme.typography.titleLarge, fontWeight = FontWeight.Bold ) }, colors = TopAppBarDefaults.topAppBarColors( containerColor = MaterialTheme.colorScheme.secondaryContainer, titleContentColor = MaterialTheme.colorScheme.onSecondaryContainer ), actions = { IconButton(onClick = {}) { Icon(Icons.Filled.Search, contentDescription = "search") } } ) } } }
方案说明
- 借助Voyager的
navigation.lastItem获取当前活跃页面,实现TopAppBar的动态切换 - BottomAppBar直接在Scaffold中全局配置,确保所有页面样式统一
- 通过
when分支对不同页面类型做差异化TopAppBar定制,后续新增页面只需扩展分支即可
内容的提问来源于stack exchange,提问作者W.A Rajinda
相关产品推荐
相关产品推荐

