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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 00:08:16