Jetpack Compose:LargeTopAppBar展开时LazyRow项顶部截断问题
Jetpack Compose LargeTopAppBar 展开状态下 LazyRow 项顶部截断问题解决
问题描述
使用Jetpack Compose的LargeTopAppBar组件时,期望展开状态显示LazyRow列表,但展开后列表项顶部被截断,即便下方仍有剩余空间。尝试动态调整顶部栏高度,问题依然存在。
原代码
主组件代码
fun AppbarDemo() { val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(rememberTopAppBarState()) val isCollapsed = remember { derivedStateOf { scrollBehavior.state.collapsedFraction > 0.5 } } val topAppBarElementColor = Color.White val collapsed = 22 val expanded = 24 val topAppBarTextSize = (collapsed + (expanded - collapsed) * (1 - scrollBehavior.state.collapsedFraction)).sp // val topBarSize = if (isCollapsed.value) 64.dp else 156.dp Scaffold( topBar = { LargeTopAppBar( title = { Column( verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.Start ) { if (isCollapsed.value) { Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center ) { if (isCollapsed.value) { Log.i("TaaAG", "anim: ") Box(contentAlignment = Alignment.Center) { StoryItem( story = Story( id = 1, userName = "", avatar = R.drawable.avatar ), size = 50, isTextVisible = false ) } // Spacer for spacing between icon and title Spacer(modifier = Modifier.width(8.dp)) Text( text = "My App", style = MaterialTheme.typography.titleLarge, fontWeight = FontWeight.Bold, modifier = Modifier.padding(4.dp), fontSize = topAppBarTextSize ) } } } else if (!isCollapsed.value) { ListSection() } } }, navigationIcon = { Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center ) { IconButton(onClick = { }) { Icon( imageVector = Icons.Default.Menu, contentDescription = "Toggle drawer" ) } if (!isCollapsed.value) { Text( text = "My App", style = MaterialTheme.typography.titleLarge, fontWeight = FontWeight.Bold, modifier = Modifier.padding(4.dp), fontSize = topAppBarTextSize ) } } }, actions = { IconButton( onClick = { /* Handle search icon click */ } ) { Icon( imageVector = Icons.Default.Search, contentDescription = "Search" ) } }, // modifier = Modifier.height(topBarSize), scrollBehavior = scrollBehavior, windowInsets = WindowInsets(0.dp), colors = TopAppBarDefaults.largeTopAppBarColors( containerColor = Color.Blue, scrolledContainerColor = Color.Blue, navigationIconContentColor = topAppBarElementColor, titleContentColor = topAppBarElementColor, actionIconContentColor = topAppBarElementColor, ), ) }, modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection) ) { innerPadding -> LazyColumn( modifier = Modifier .fillMaxSize() .padding(innerPadding) ) { items(30) { Text( text = "some data", style = MaterialTheme.typography.headlineMedium, modifier = Modifier.padding(15.dp) ) } } } }
LazyRow及子项代码
fun ListSection() { Box( Modifier .background(color = Color.Blue) ) { LazyRow( modifier = Modifier .fillMaxWidth() .wrapContentHeight() ) { items(10) { ListItem(60) } } } } @Composable fun ListItem(size: Int) { Column( verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { Box { Box( Modifier .height(size.dp) .width(size.dp) .padding(5.dp) .border( shape = CircleShape, border = BorderStroke( width = 2.dp, brush = Brush.linearGradient( colors = BorderGradient, start = Offset( 0f, 0f ), end = Offset( 100f, 100f ) ) ) ), contentAlignment = Alignment.Center ) { val decreasedSize = size - 20 Image( painter = painterResource(R.drawable.avatar), contentDescription = null, modifier = Modifier .size(decreasedSize.dp) .clip(CircleShape) ) } } Text( text = "person", fontSize = 8.sp, color = Color.White, style = MaterialTheme.typography.bodySmall, textAlign = TextAlign.Center ) } }
解决方案
问题根源在于LargeTopAppBar的标题区域默认有固定布局约束,加上标题Column的垂直居中设置,导致LazyRow内容被顶部截断。以下是具体修改:
1. 调整标题Column的布局对齐
将标题区域的Column的verticalArrangement从Arrangement.Center改为Arrangement.Top,并添加顶部内边距,确保内容从顶部开始排列:
title = { Column( verticalArrangement = Arrangement.Top, horizontalAlignment = Alignment.Start, modifier = Modifier.padding(top = 16.dp) // 添加顶部内边距 ) { // 原有内容... } }
2. 简化ListSection布局
移除ListSection中多余的Box背景(LargeTopAppBar已有蓝色背景),直接保留LazyRow并添加上下内边距:
fun ListSection() { LazyRow( modifier = Modifier .fillMaxWidth() .wrapContentHeight() .padding(vertical = 8.dp), // 添加上下内边距 horizontalArrangement = Arrangement.spacedBy(8.dp) // 列表项间距 ) { items(10) { ListItem(60) } } }
修改后的完整主组件代码片段
fun AppbarDemo() { val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(rememberTopAppBarState()) val isCollapsed = remember { derivedStateOf { scrollBehavior.state.collapsedFraction > 0.5 } } val topAppBarElementColor = Color.White val collapsed = 22 val expanded = 24 val topAppBarTextSize = (collapsed + (expanded - collapsed) * (1 - scrollBehavior.state.collapsedFraction)).sp Scaffold( topBar = { LargeTopAppBar( title = { Column( verticalArrangement = Arrangement.Top, horizontalAlignment = Alignment.Start, modifier = Modifier.padding(top = 16.dp) ) { if (isCollapsed.value) { Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center ) { Box(contentAlignment = Alignment.Center) { StoryItem( story = Story( id = 1, userName = "", avatar = R.drawable.avatar ), size = 50, isTextVisible = false ) } Spacer(modifier = Modifier.width(8.dp)) Text( text = "My App", style = MaterialTheme.typography.titleLarge, fontWeight = FontWeight.Bold, modifier = Modifier.padding(4.dp), fontSize = topAppBarTextSize ) } } else { ListSection() } } }, navigationIcon = { Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center ) { IconButton(onClick = { }) { Icon( imageVector = Icons.Default.Menu, contentDescription = "Toggle drawer" ) } if (!isCollapsed.value) { Text( text = "My App", style = MaterialTheme.typography.titleLarge, fontWeight = FontWeight.Bold, modifier = Modifier.padding(4.dp), fontSize = topAppBarTextSize ) } } }, actions = { IconButton(onClick = { }) { Icon( imageVector = Icons.Default.Search, contentDescription = "Search" ) } }, scrollBehavior = scrollBehavior, windowInsets = WindowInsets(0.dp), colors = TopAppBarDefaults.largeTopAppBarColors( containerColor = Color.Blue, scrolledContainerColor = Color.Blue, navigationIconContentColor = topAppBarElementColor, titleContentColor = topAppBarElementColor, actionIconContentColor = topAppBarElementColor, ), ) }, modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection) ) { innerPadding -> LazyColumn( modifier = Modifier .fillMaxSize() .padding(innerPadding) ) { items(30) { Text( text = "some data", style = MaterialTheme.typography.headlineMedium, modifier = Modifier.padding(15.dp) ) } } } }
修改后,LargeTopAppBar展开状态下的LazyRow列表项会完整显示,不会出现顶部截断问题。
内容的提问来源于stack exchange,提问作者Ftm Amani
相关产品推荐
相关产品推荐

