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

实现LazyColumn滚动时仅首项可见才显示TopAppBar

自定义TopAppBar滚动行为:仅当LazyColumn首项可见时显示

我基于Android Developers的示例实现了一个TopAppBar,原本逻辑是LazyColumn向下滚动时TopAppBar消失,向上滚动时显示。之后我在列表上方添加了一个Box组件,功能正常,但希望调整滚动行为:仅当LazyColumn的第一个列表项(内容为'0')重新可见时,TopAppBar才显示出来,而不是只要向上滚动就触发显示。

原实现代码

@OptIn(ExperimentalMaterial3Api::class)
@Preview
@Composable
fun TopAppBarSample() {
    val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
    Scaffold(
        modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
        topBar = {
            TopAppBar(
                title = {
                    Text(
                        "TopAppBar",
                        maxLines = 1,
                        overflow = TextOverflow.Ellipsis
                    )
                },
                navigationIcon = {
                    IconButton(onClick = { /* doSomething() */ }) {
                        Icon(
                            imageVector = Icons.Filled.Menu,
                            contentDescription = "Localized description"
                        )
                    }
                },
                actions = {
                    // RowScope here, so these icons will be placed horizontally
                    IconButton(onClick = { /* doSomething() */ }) {
                        Icon(
                            imageVector = Icons.Filled.Favorite,
                            contentDescription = "Localized description"
                        )
                    }
                    IconButton(onClick = { /* doSomething() */ }) {
                        Icon(
                            imageVector = Icons.Filled.Favorite,
                            contentDescription = "Localized description"
                        )
                    }
                },
                scrollBehavior = scrollBehavior
            )
        },
        content = { innerPadding ->
            Column(modifier = Modifier.padding(paddingValues = innerPadding)) {
                Box(
                    modifier = Modifier
                        .size(200.dp)
                        .background(Color.Gray)
                ) {

                }

                LazyColumn(
                    contentPadding = innerPadding,
                    verticalArrangement = Arrangement.spacedBy(8.dp)
                ) {
                    val list = (0..75).map { it.toString() }
                    items(count = list.size) {
                        Text(
                            text = list[it],
                            style = MaterialTheme.typography.bodyLarge,
                            modifier = Modifier
                                .fillMaxWidth()
                                .padding(horizontal = 16.dp)
                        )
                    }
                }
            }
        }
    )
}

修改后的实现方案

核心思路是通过LazyListState跟踪LazyColumn的滚动状态,仅当首项完全可见时才触发TopAppBar的显示:

@OptIn(ExperimentalMaterial3Api::class)
@Preview
@Composable
fun TopAppBarSample() {
    val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
    val lazyListState = rememberLazyListState()
    val scope = rememberCoroutineScope()

    // 监听首项可见状态,控制TopAppBar显示
    LaunchedEffect(lazyListState) {
        snapshotFlow {
            // 判断首项是否完全可见:索引为0且滚动偏移量为0
            lazyListState.firstVisibleItemIndex == 0 && lazyListState.firstVisibleItemScrollOffset == 0
        }.collect { isFirstItemVisible ->
            if (isFirstItemVisible) {
                // 平滑滚动TopAppBar到完全显示状态
                scope.launch {
                    scrollBehavior.state.animateScrollTo(0)
                }
            }
        }
    }

    Scaffold(
        modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
        topBar = {
            TopAppBar(
                title = {
                    Text(
                        "TopAppBar",
                        maxLines = 1,
                        overflow = TextOverflow.Ellipsis
                    )
                },
                navigationIcon = {
                    IconButton(onClick = { /* doSomething() */ }) {
                        Icon(
                            imageVector = Icons.Filled.Menu,
                            contentDescription = "菜单"
                        )
                    }
                },
                actions = {
                    IconButton(onClick = { /* doSomething() */ }) {
                        Icon(
                            imageVector = Icons.Filled.Favorite,
                            contentDescription = "收藏"
                        )
                    }
                    IconButton(onClick = { /* doSomething() */ }) {
                        Icon(
                            imageVector = Icons.Filled.Favorite,
                            contentDescription = "收藏"
                        )
                    }
                },
                scrollBehavior = scrollBehavior
            )
        },
        content = { innerPadding ->
            Column(modifier = Modifier.padding(paddingValues = innerPadding)) {
                Box(
                    modifier = Modifier
                        .size(200.dp)
                        .background(Color.Gray)
                )

                LazyColumn(
                    state = lazyListState, // 绑定LazyListState
                    contentPadding = innerPadding,
                    verticalArrangement = Arrangement.spacedBy(8.dp)
                ) {
                    val list = (0..75).map { it.toString() }
                    items(count = list.size) {
                        Text(
                            text = list[it],
                            style = MaterialTheme.typography.bodyLarge,
                            modifier = Modifier
                                .fillMaxWidth()
                                .padding(horizontal = 16.dp)
                        )
                    }
                }
            }
        }
    )
}

关键修改说明

  • 绑定LazyListState:给LazyColumn添加state = lazyListState,用于跟踪列表的滚动位置和可见项状态
  • 监听首项可见性:通过snapshotFlow监听lazyListState的变化,当firstVisibleItemIndex为0且firstVisibleItemScrollOffset为0时,判定首项完全可见
  • 控制TopAppBar显示:当首项完全可见时,通过scrollBehavior.state.animateScrollTo(0)让TopAppBar平滑滚动到完全显示状态;向下滚动隐藏的逻辑保持原有行为不变

内容的提问来源于stack exchange,提问作者Kinyo356

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 06:55:25