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

Jetpack Compose:TopAppBar可折叠但SearchView无法折叠问题

解决方案

问题出在你仅把滚动行为绑定到了MediumTopAppBar上,SearchBar没有和滚动状态联动,所以无法随TopAppBar一起折叠。下面是修改后的代码,实现TopAppBar与SearchView同步折叠、TabLayout固定顶部的效果:

@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
@Composable
fun MyCollapsingLayout() {
    val tabs = listOf("Tab 1", "Tab 2", "Tab 3")
    var selectedTabIndex by remember { mutableIntStateOf(0) }
    val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
    val scrollState = scrollBehavior.state
    var searchBarHeight by remember { mutableIntStateOf(0) }
    val listState = rememberLazyListState()

    Scaffold(
        topBar = {
            // 将TopAppBar和SearchBar放在同一个Column中,绑定滚动行为并控制整体偏移
            Column(
                modifier = Modifier
                    .nestedScroll(scrollBehavior.nestedScrollConnection)
                    .fillMaxWidth()
                    // 根据滚动状态调整顶部区域的垂直偏移,让SearchBar随TopAppBar折叠隐藏
                    .offset {
                        // 最大偏移量为SearchBar的高度,确保完全隐藏
                        val maxOffset = -searchBarHeight
                        // 取滚动偏移与最大偏移的较大值,避免过度偏移
                        IntOffset(0, scrollState.offset.toInt().coerceAtLeast(maxOffset))
                    }
            ) {
                MediumTopAppBar(
                    title = { Text("Medium AppBar") },
                    scrollBehavior = scrollBehavior
                )

                SearchBar(
                    modifier = Modifier
                        // 获取SearchBar的实际高度,用于计算偏移量
                        .onGloballyPositioned { searchBarHeight = it.size.height }
                )
            }
        },
        content = { padding ->
            LazyColumn(
                state = listState,
                modifier = Modifier
                    .fillMaxSize()
                    .padding(padding)
            ) {
                // 粘性Header保持TabRow固定在顶部
                stickyHeader {
                    TabRow(
                        selectedTabIndex = selectedTabIndex,
                        modifier = Modifier.fillMaxWidth()
                    ) {
                        tabs.forEachIndexed { index, tab ->
                            Tab(
                                selected = selectedTabIndex == index,
                                onClick = { selectedTabIndex = index },
                                text = { Text(tab) }
                            )
                        }
                    }
                }

                items(50) { index ->
                    ListItem(text = "Item $index")
                }
            }
        }
    )
}

@Composable
fun SearchBar(modifier: Modifier = Modifier) {
    TextField(
        value = "",
        onValueChange = {},
        placeholder = { Text("Search...") },
        modifier = modifier
            .fillMaxWidth()
            .padding(8.dp)
    )
}

@Composable
fun ListItem(text: String) {
    Text(
        text = text,
        modifier = Modifier
            .fillMaxWidth()
            .padding(16.dp)
    )
}

关键修改点

  1. 绑定整体滚动行为:将nestedScroll绑定到包含TopAppBar和SearchBar的Column上,让整个顶部区域响应滚动事件。
  2. 动态计算偏移量:通过onGloballyPositioned获取SearchBar的实际高度,结合scrollState.offset控制整个Column的垂直偏移,当TopAppBar折叠时,SearchBar同步向上移出屏幕。
  3. 保持Tab固定:TabRow放在LazyColumn的stickyHeader中,滚动时会自动固定在屏幕顶部。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 10:29:54