如何让 LazyColumn 具有像文本 ("You are at the Top of the List") 这样的可组合项,它会随着列表变大而消失?
How to have a LazyColumn with a Composable like a Text("You are at the Top of the List"), which fades away as the list turns bigger?
我有一个 Column 和一个 LazyColumn,代码如下:
Column {
LazyColumn(
modifier = Modifier.weight(1f),
contentPadding = PaddingValues(top = 8.dp)
) {
items(items = items) { it ->
TodoRow(
todo = it,
onItemClicked = { onRemoveItem(it) },
modifier = Modifier.fillParentMaxWidth()
)
}
}
}
我想得到的是:
- 要有一个 Box() 和一个 Text() 来说明我们在“列表的顶部”;
- 无法修复带有 Text() 的 Box()。也就是说,它会随着列表变大并占据整个屏幕而消失。如果我们向上滚动 Text() 再次出现。
对于带有文本的框,我有以下代码:
Box(
modifier = Modifier
.fillMaxWidth()
.padding(start = 8.dp, end = 8.dp)
.background(color = Color.LightGray),
contentAlignment = Alignment.Center
)
{ Text("Top of the List", modifier = Modifier.padding(vertical = 8.dp)) }
如果我将此 Box 作为上述 Column 的子项放在 LazyColumn 之前,此 Box 将被固定,我不希望这样。
那么,我应该把这个盒子放在哪里呢?你能帮帮我吗?
谢谢
您可以从列表状态读取滚动位置。根据位置,您可以计算“动画”的进度。
Column {
val listState = rememberLazyListState()
val topOfListProgress: Float by remember {
derivedStateOf {
listState.run {
if (firstVisibleItemIndex > 0) {
0f
} else {
layoutInfo.visibleItemsInfo
.firstOrNull()
?.let {
1f - firstVisibleItemScrollOffset.toFloat() / it.size
} ?: 1f
}
}
}
}
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.fillMaxWidth()
.padding(start = 8.dp, end = 8.dp)
.background(color = Color.LightGray)
.layout { measurable, constraints ->
val placeable = measurable.measure(constraints)
val offset = (placeable.height * (1f - topOfListProgress)).roundToInt()
layout(placeable.width, placeable.height - offset) {
placeable.place(0, -offset)
}
}
.alpha(topOfListProgress)
) {
Text("Top of the List", modifier = Modifier.padding(vertical = 8.dp))
}
LazyColumn(
state = listState,
contentPadding = PaddingValues(top = 8.dp),
modifier = Modifier
.weight(1f)
) {
items(100) {
Text(it.toString())
}
}
}
结果:
我有一个 Column 和一个 LazyColumn,代码如下:
Column {
LazyColumn(
modifier = Modifier.weight(1f),
contentPadding = PaddingValues(top = 8.dp)
) {
items(items = items) { it ->
TodoRow(
todo = it,
onItemClicked = { onRemoveItem(it) },
modifier = Modifier.fillParentMaxWidth()
)
}
}
}
我想得到的是:
- 要有一个 Box() 和一个 Text() 来说明我们在“列表的顶部”;
- 无法修复带有 Text() 的 Box()。也就是说,它会随着列表变大并占据整个屏幕而消失。如果我们向上滚动 Text() 再次出现。
对于带有文本的框,我有以下代码:
Box(
modifier = Modifier
.fillMaxWidth()
.padding(start = 8.dp, end = 8.dp)
.background(color = Color.LightGray),
contentAlignment = Alignment.Center
)
{ Text("Top of the List", modifier = Modifier.padding(vertical = 8.dp)) }
如果我将此 Box 作为上述 Column 的子项放在 LazyColumn 之前,此 Box 将被固定,我不希望这样。
那么,我应该把这个盒子放在哪里呢?你能帮帮我吗?
谢谢
您可以从列表状态读取滚动位置。根据位置,您可以计算“动画”的进度。
Column {
val listState = rememberLazyListState()
val topOfListProgress: Float by remember {
derivedStateOf {
listState.run {
if (firstVisibleItemIndex > 0) {
0f
} else {
layoutInfo.visibleItemsInfo
.firstOrNull()
?.let {
1f - firstVisibleItemScrollOffset.toFloat() / it.size
} ?: 1f
}
}
}
}
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.fillMaxWidth()
.padding(start = 8.dp, end = 8.dp)
.background(color = Color.LightGray)
.layout { measurable, constraints ->
val placeable = measurable.measure(constraints)
val offset = (placeable.height * (1f - topOfListProgress)).roundToInt()
layout(placeable.width, placeable.height - offset) {
placeable.place(0, -offset)
}
}
.alpha(topOfListProgress)
) {
Text("Top of the List", modifier = Modifier.padding(vertical = 8.dp))
}
LazyColumn(
state = listState,
contentPadding = PaddingValues(top = 8.dp),
modifier = Modifier
.weight(1f)
) {
items(100) {
Text(it.toString())
}
}
}
结果: