Jetpack Compose 如何实现标签栏位于屏幕底部、底部导航栏上方的布局
实现方案
整体采用双层Scaffold分层+自动padding避让的逻辑实现,层级顺序从下到上(视觉上从顶部到底部)依次为:标签页内容区域、页面级标签栏、全局底部导航栏。
步骤1:配置全局根布局
全局唯一的根Scaffold只负责承载App共用的底部导航栏,所有业务页面作为根Scaffold的content区域子节点渲染,自动避让底部导航的高度:
@Composable fun AppRootScreen() { val rootNavController = rememberNavController() Scaffold( // 仅在这里配置全局共用的底部导航栏 bottomBar = { AppBottomNavigation(navController = rootNavController) } ) { rootInnerPadding -> NavHost( navController = rootNavController, startDestination = "home", modifier = Modifier.padding(rootInnerPadding) ) { // 其他页面路由 composable("home") { HomeScreen() } // 需要加标签栏的目标页面路由 composable("tab_page") { TabPageScreen() } } } }
步骤2:实现带标签栏的目标页面
在目标页面内部用Column做垂直布局,通过weight属性让内容区域占满标签栏之外的所有空间,标签栏自然排列在内容下方、全局底部导航上方:
@Composable fun TabPageScreen() { // 3个标签页示例,可根据业务调整数量 val tabTitles = listOf("标签1", "标签2", "标签3") val pagerState = rememberPagerState(pageCount = { tabTitles.size }) val coroutineScope = rememberCoroutineScope() Column(modifier = Modifier.fillMaxSize()) { // 标签页内容区域,排列在最上方 HorizontalPager( state = pagerState, modifier = Modifier.weight(1f) // weight(1f)自动占满Column剩余高度 ) { pageIndex -> when(pageIndex) { 0 -> TabContent1() 1 -> TabContent2() 2 -> TabContent3() } } // 标签栏,排列在内容区域下方、全局底部导航上方 TabRow( selectedTabIndex = pagerState.currentPage, modifier = Modifier.fillMaxWidth() ) { tabTitles.forEachIndexed { index, title -> Tab( selected = pagerState.currentPage == index, onClick = { coroutineScope.launch { pagerState.animateScrollToPage(index) } }, text = { Text(title) } ) } } } }
注意事项
- 不要将页面级标签栏配置到根Scaffold的
bottomBar参数中,否则会直接替换全局底部导航栏 - 如果需要支持滚动时隐藏标签栏,可以把页面内部的Column替换为页面级Scaffold,将标签栏配置到该Scaffold的
bottomBar参数即可,内容区域通过页面级Scaffold的innerPadding自动避让 - 全程不需要写固定高度,通过
weight或者Scaffold自动padding即可适配所有屏幕尺寸
内容的提问来源于stack exchange,提问作者Annon
相关产品推荐
相关产品推荐

