Jetpack Compose 折叠工具栏
Jetpack Compose collapsing toolbar
我找不到关于此事的任何文档,Compose 中是否有类似于 CollapsingToolbar
的内容?
我找到的只是提及它 here,但没有关于如何设置它的内容
我找到了一个由 Samir Basnet(来自 Kotlin Slack Channel)创建的解决方案,它对我很有用,我希望它能帮助其他人...
@Composable
fun CollapsingEffectScreen() {
val items = (1..100).map { "Item $it" }
val lazyListState = rememberLazyListState()
var scrolledY = 0f
var previousOffset = 0
LazyColumn(
Modifier.fillMaxSize(),
lazyListState,
) {
item {
Image(
painter = painterResource(id = R.drawable.recife),
contentDescription = null,
contentScale = ContentScale.FillWidth,
modifier = Modifier
.graphicsLayer {
scrolledY += lazyListState.firstVisibleItemScrollOffset - previousOffset
translationY = scrolledY * 0.5f
previousOffset = lazyListState.firstVisibleItemScrollOffset
}
.height(240.dp)
.fillMaxWidth()
)
}
items(items) {
Text(
text = it,
Modifier
.background(Color.White)
.fillMaxWidth()
.padding(8.dp)
)
}
}
}
结果如下:
我在 Android 文档中找到了这个,我认为您在问题中链接的文档正在谈论如何使用嵌套滚动来实现这一点。
val toolbarHeight = 48.dp
val toolbarHeightPx = with(LocalDensity.current) { toolbarHeight.roundToPx().toFloat() }
val toolbarOffsetHeightPx = remember { mutableStateOf(0f) }
val nestedScrollConnection = remember {
object : NestedScrollConnection {
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
val delta = available.y
val newOffset = toolbarOffsetHeightPx.value + delta
toolbarOffsetHeightPx.value = newOffset.coerceIn(-toolbarHeightPx, 0f)
return Offset.Zero
}
}
}
Box(
Modifier
.fillMaxSize()
.nestedScroll(nestedScrollConnection)
) {
LazyColumn(contentPadding = PaddingValues(top = toolbarHeight)) {
items(100) { index ->
Text("I'm item $index", modifier = Modifier
.fillMaxWidth()
.padding(16.dp))
}
}
TopAppBar(
modifier = Modifier
.height(toolbarHeight)
.offset { IntOffset(x = 0, y = toolbarOffsetHeightPx.value.roundToInt()) },
title = { Text("toolbar offset is ${toolbarOffsetHeightPx.value}") }
)
}
您可以使用 compose-collapsing-toolbar 库。
安装 : implementation "me.onebone:toolbar-compose:2.1.0"
预览
这里有一些来自图书馆 Readme.md 的 gif 图片:
您可以按照 example in the docs 创建一个工具栏,在每个滚动 up/down 上 expands/collapses。
要创建一个仅当列表滚动到顶部时才展开的工具栏,您可以对原始示例稍作修改:
val toolbarHeight = 48.dp
val toolbarHeightPx = with(LocalDensity.current) { toolbarHeight.roundToPx().toFloat() }
var toolbarOffsetHeightPx by remember { mutableStateOf(0f) }
var totalScrollOffsetPx = remember { 0f }
val nestedScrollConnection = remember {
object : NestedScrollConnection {
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
val delta = available.y
totalScrollOffsetPx += delta
if (totalScrollOffsetPx in -toolbarHeightPx..0f) {
toolbarOffsetHeightPx = totalScrollOffsetPx
}
return Offset.Zero
}
}
}
通过这样做,您可以灵活地创建自己的 CollapsibleScaffold
,它可以接受 scrollBehaviour
、appBarLayout
和 list
等可组合项等参数.
这样,例如,您还可以通过编程方式计算应用栏的高度并摆脱大量样板文件,使屏幕中使用的代码整洁干净。
撰写折叠工具栏
Jetpack Compose
的 CollapsingToolbarLayout 的简单实现
Material 设计 3 的 Jetpack Compose 实施包括 4 种类型的热门应用栏 (https://m3.material.io/components/top-app-bar/implementation):
CenterAlignedTopAppBar
SmallTopAppBar
MediumTopAppBar
LargeTopAppBar
https://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary
它们都有一个scrollBehavior
参数,可用于折叠工具栏。库中有 3 种基本类型的滚动行为:
TopAppBarDefaults.pinnedScrollBehavior
TopAppBarDefaults.enterAlwaysScrollBehavior
TopAppBarDefaults.exitUntilCollapsedScrollBehavior
https://developer.android.com/reference/kotlin/androidx/compose/material3/TopAppBarDefaults
注意:这个API目前被注释为实验性的。
示例用法:
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun Test() {
val scrollBehavior = remember { TopAppBarDefaults.enterAlwaysScrollBehavior() }
Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = {
MediumTopAppBar(
title = { Text(text = "Scroll Behavior Test") },
navigationIcon = {
IconButton(onClick = { /*TODO*/ }) {
Icon(imageVector = Icons.Default.Menu, contentDescription = "")
}
},
scrollBehavior = scrollBehavior
)
}
) {
LazyColumn(modifier = Modifier.fillMaxWidth()) {
items((1..50).toList()) { item ->
Text(modifier = Modifier.padding(8.dp), text = "Item $item")
}
}
}
}
我找不到关于此事的任何文档,Compose 中是否有类似于 CollapsingToolbar
的内容?
我找到的只是提及它 here,但没有关于如何设置它的内容
我找到了一个由 Samir Basnet(来自 Kotlin Slack Channel)创建的解决方案,它对我很有用,我希望它能帮助其他人...
@Composable
fun CollapsingEffectScreen() {
val items = (1..100).map { "Item $it" }
val lazyListState = rememberLazyListState()
var scrolledY = 0f
var previousOffset = 0
LazyColumn(
Modifier.fillMaxSize(),
lazyListState,
) {
item {
Image(
painter = painterResource(id = R.drawable.recife),
contentDescription = null,
contentScale = ContentScale.FillWidth,
modifier = Modifier
.graphicsLayer {
scrolledY += lazyListState.firstVisibleItemScrollOffset - previousOffset
translationY = scrolledY * 0.5f
previousOffset = lazyListState.firstVisibleItemScrollOffset
}
.height(240.dp)
.fillMaxWidth()
)
}
items(items) {
Text(
text = it,
Modifier
.background(Color.White)
.fillMaxWidth()
.padding(8.dp)
)
}
}
}
结果如下:
我在 Android 文档中找到了这个,我认为您在问题中链接的文档正在谈论如何使用嵌套滚动来实现这一点。
val toolbarHeight = 48.dp
val toolbarHeightPx = with(LocalDensity.current) { toolbarHeight.roundToPx().toFloat() }
val toolbarOffsetHeightPx = remember { mutableStateOf(0f) }
val nestedScrollConnection = remember {
object : NestedScrollConnection {
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
val delta = available.y
val newOffset = toolbarOffsetHeightPx.value + delta
toolbarOffsetHeightPx.value = newOffset.coerceIn(-toolbarHeightPx, 0f)
return Offset.Zero
}
}
}
Box(
Modifier
.fillMaxSize()
.nestedScroll(nestedScrollConnection)
) {
LazyColumn(contentPadding = PaddingValues(top = toolbarHeight)) {
items(100) { index ->
Text("I'm item $index", modifier = Modifier
.fillMaxWidth()
.padding(16.dp))
}
}
TopAppBar(
modifier = Modifier
.height(toolbarHeight)
.offset { IntOffset(x = 0, y = toolbarOffsetHeightPx.value.roundToInt()) },
title = { Text("toolbar offset is ${toolbarOffsetHeightPx.value}") }
)
}
您可以使用 compose-collapsing-toolbar 库。
安装 : implementation "me.onebone:toolbar-compose:2.1.0"
预览
这里有一些来自图书馆 Readme.md 的 gif 图片:
您可以按照 example in the docs 创建一个工具栏,在每个滚动 up/down 上 expands/collapses。
要创建一个仅当列表滚动到顶部时才展开的工具栏,您可以对原始示例稍作修改:
val toolbarHeight = 48.dp
val toolbarHeightPx = with(LocalDensity.current) { toolbarHeight.roundToPx().toFloat() }
var toolbarOffsetHeightPx by remember { mutableStateOf(0f) }
var totalScrollOffsetPx = remember { 0f }
val nestedScrollConnection = remember {
object : NestedScrollConnection {
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
val delta = available.y
totalScrollOffsetPx += delta
if (totalScrollOffsetPx in -toolbarHeightPx..0f) {
toolbarOffsetHeightPx = totalScrollOffsetPx
}
return Offset.Zero
}
}
}
通过这样做,您可以灵活地创建自己的 CollapsibleScaffold
,它可以接受 scrollBehaviour
、appBarLayout
和 list
等可组合项等参数.
这样,例如,您还可以通过编程方式计算应用栏的高度并摆脱大量样板文件,使屏幕中使用的代码整洁干净。
撰写折叠工具栏 Jetpack Compose
的 CollapsingToolbarLayout 的简单实现Material 设计 3 的 Jetpack Compose 实施包括 4 种类型的热门应用栏 (https://m3.material.io/components/top-app-bar/implementation):
CenterAlignedTopAppBar
SmallTopAppBar
MediumTopAppBar
LargeTopAppBar
https://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary
它们都有一个scrollBehavior
参数,可用于折叠工具栏。库中有 3 种基本类型的滚动行为:
TopAppBarDefaults.pinnedScrollBehavior
TopAppBarDefaults.enterAlwaysScrollBehavior
TopAppBarDefaults.exitUntilCollapsedScrollBehavior
https://developer.android.com/reference/kotlin/androidx/compose/material3/TopAppBarDefaults
注意:这个API目前被注释为实验性的。
示例用法:
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun Test() {
val scrollBehavior = remember { TopAppBarDefaults.enterAlwaysScrollBehavior() }
Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = {
MediumTopAppBar(
title = { Text(text = "Scroll Behavior Test") },
navigationIcon = {
IconButton(onClick = { /*TODO*/ }) {
Icon(imageVector = Icons.Default.Menu, contentDescription = "")
}
},
scrollBehavior = scrollBehavior
)
}
) {
LazyColumn(modifier = Modifier.fillMaxWidth()) {
items((1..50).toList()) { item ->
Text(modifier = Modifier.padding(8.dp), text = "Item $item")
}
}
}
}