这一节主要了解一下Compose折叠AppBar,在Compose中实现类似Android原生CollapsingToolbarLayout+AppBarLayout的滑动折叠标题栏效果,官方提供了Scaffold+TopAppBar+NestedScroll Connection标准方案,核心依赖 TopAppBar/LargeTopAppBar、scrollBehavior以及嵌套滚动机制,无需自定义复杂布局,简单总结如下:
API:
LargeTopAppBar:Material3提供的可折叠顶部栏,自带展开/折叠两种形态;
rememberTopAppBarState:核心滚动行为,滚动时标题栏逐渐折叠,完全折叠后固定在顶部;
NestedScrollConnection:连接滚动容器(LazyColumn/Column)与顶部栏,实现联动折叠;
Scaffold:标准页面骨架,自动处理滚动区域与AppBar的嵌套;
栗子:
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material.icons.filled.Search
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LargeTopAppBar
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun CollapsingAppBarDemo() {
val topAppBarState = rememberTopAppBarState()
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(
state = topAppBarState,
)
Scaffold(
topBar = {
LargeTopAppBar(
title = {
Text(
text = "折叠标题栏演示",
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
},
navigationIcon = {
IconButton(onClick = { /* 打开侧边栏 */ }) {
Icon(Icons.Default.Menu, contentDescription = "菜单")
}
},
actions = {
IconButton(onClick = { /* 搜索功能 */ }) {
Icon(Icons.Default.Search, contentDescription = "搜索")
}
},
scrollBehavior = scrollBehavior
)
},
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection)
) { innerPadding ->
LazyColumn(
modifier = Modifier
.fillMaxSize()
.padding(innerPadding),
verticalArrangement = androidx.compose.foundation.layout.Arrangement.spacedBy(8.dp)
) {
items(50) { index ->
Box(
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 16.dp, vertical = 12.dp)
) {
Text(text = "列表项 $index", style = MaterialTheme.typography.bodyLarge)
}
}
}
}
}
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material3.Card
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LargeTopAppBar
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun CollapsingAppBarDemo() {
val topAppBarState = rememberTopAppBarState()
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(topAppBarState)
val collapseProgress = topAppBarState.collapsedFraction
val titleAlpha by animateFloatAsState(
targetValue = if (collapseProgress > 0.5f) 1f else 0.7f,
label = "title_alpha_anim"
)
Scaffold(
topBar = {
LargeTopAppBar(
title = {
Text(
text = "自定义折叠标题栏",
modifier = Modifier.alpha(titleAlpha),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
style = MaterialTheme.typography.headlineSmall
)
},
navigationIcon = {
IconButton(onClick = {}) {
Icon(Icons.Default.Menu, "导航菜单")
}
},
actions = {
IconButton(onClick = {}) {
Icon(Icons.Default.Settings, "设置")
}
},
scrollBehavior = scrollBehavior,
colors = TopAppBarDefaults.largeTopAppBarColors(
scrolledContainerColor = MaterialTheme.colorScheme.secondaryContainer
)
)
},
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection)
) { innerPadding ->
LazyColumn(
modifier = Modifier
.fillMaxSize()
.padding(innerPadding)
.padding(horizontal = 16.dp),
verticalArrangement = androidx.compose.foundation.layout.Arrangement.spacedBy(12.dp)
) {
items(60) { index ->
Card(
modifier = Modifier.fillMaxSize(),
shape = androidx.compose.foundation.shape.RoundedCornerShape(8.dp)
) {
Box(modifier = Modifier.padding(20.dp)) {
Text(text = "折叠列表项 $index", style = MaterialTheme.typography.bodyLarge)
}
}
}
}
}
}
注意:
1 必须绑定scrollBehavior且关联嵌套滚动;
2 滚动容器必须是“可滚动组件”;
3 必须使用Scaffold且正确处理innerPadding,如LargeTopAppBar必须放在Scaffold的topBar参数中,内容容器必须应用Scaffold回调的innerPadding;
转载自CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/ljt2724960661/article/details/158012946



