Jetpack Compose中如何让Material3 Scaffold内容延伸至TopBar且不遮挡TabRow
问题解决:Material3 Scaffold内容延伸至TopBar且粘性TabRow不重叠
需求
让Material3 Scaffold的内容区域延伸至TopBar下方,但向下滚动时,内容中的粘性TabRow头部不能与TopBar重叠。当前设置LazyColumn顶部内边距为0.dp后,内容已延伸至TopBar,但滚动时TabRow停在屏幕顶部而非TopBar下方。
解决方案
核心思路是获取TopAppBar的实际高度,给粘性TabRow设置顶部偏移,使其滚动时停在TopBar下方:
- 监听TopAppBar尺寸变化,记录真实高度,避免依赖固定值适配不同设备
- 给粘性头部的ScrollableTabRow添加顶部内边距,值为TopAppBar的高度,确保滚动时无重叠
- 保持TopAppBar与LazyColumn滚动行为联动,保证交互一致性
修改后的代码
@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class) @Composable fun ProfileScreen() { var selectedTabIndex by remember { mutableIntStateOf(0) } val tabTitles = listOf("About", "Moments") val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior() // 记录TopAppBar的实际高度 val topBarHeight = remember { mutableIntStateOf(0) } Scaffold( topBar = { TopAppBar( title = {}, navigationIcon = { IconButton(onClick = { }) { Icon( imageVector = Icons.Filled.ArrowBack, contentDescription = "返回" ) } }, colors = topAppBarColors( containerColor = Color.Transparent, scrolledContainerColor = Color.Transparent ), scrollBehavior = scrollBehavior, // 监听尺寸变化保存TopAppBar高度 modifier = Modifier.onSizeChanged { topBarHeight.intValue = it.height } ) }, bottomBar = { Divider(modifier = Modifier.clip(RoundedCornerShape(20.dp))) Button( onClick = {}, modifier = Modifier .fillMaxWidth() .padding(20.dp) ) { Text("编辑资料") } } ) { paddingValue -> LazyColumn( modifier = Modifier .fillMaxSize() .background(onBackgroundDark) .padding(bottom = paddingValue.calculateBottomPadding()), state = rememberLazyListState(), contentPadding = PaddingValues(top = 0.dp) ) { item { HeaderBackground() } item { ProfileUserSection() } stickyHeader { ScrollableTabRow( selectedTabIndex = selectedTabIndex, modifier = Modifier // 设置顶部内边距,让TabRow停在TopBar下方 .padding(top = topBarHeight.intValue.dp) .padding(horizontal = 10.dp) .fillMaxWidth() .clip(RoundedCornerShape(20.dp, 20.dp, 0.dp, 0.dp)), edgePadding = 0.dp, divider = {} ) { tabTitles.forEachIndexed { index, title -> Tab( selected = selectedTabIndex == index, onClick = { selectedTabIndex = index }, text = { Text(title) } ) } } } item { when (selectedTabIndex) { 0 -> TabAbout() 1 -> TabMoments() } } } } }
效果说明
- 初始状态:内容完整延伸至TopBar下方,TabRow随内容正常滚动
- 滚动后:TabRow固定在TopBar下方,不会与TopBar产生重叠
内容的提问来源于stack exchange,提问作者Lzpeng
相关产品推荐
相关产品推荐

