目前在Jetpack Compose中,这段代码会抛出IllegalStateException,因为你不能嵌套两个垂直滚动的组件。
这并不完全正确,它所说的是你不能将Constraints.Infinity传递给另一个可滚动的组合。带有滚动修饰符的LazyLists组合也依赖于不允许使用无限的maxWidth/Height来测量自身。如果你将maxHeight更改为有限的值,就不会遇到这个问题。约束意味着在放置组合之前测量它们的范围。如果你传递一个0-有限的尺寸,它将以该尺寸进行测量。
如果你的垂直网格内容比父级高度减去其他内容高度的总和小,那么你也不需要指定固定的高度。
使用Modifier.heightIn(max)将其传递,你可以将网格的高度测量约束为0且位于父级之间。
@Preview
@Composable
private fun LazyTest() {
BoxWithConstraints {
val parentHeight = maxHeight
LazyColumn {
item {
Text(text = "My LazyColumn Title")
}
item {
LazyVerticalGrid(
modifier = Modifier.heightIn(max = parentHeight),
columns = GridCells.Fixed(4)
) {
items(10) {
Box(
modifier = Modifier
.size(50.dp)
.padding(5.dp)
.background(Color.Gray)
)
}
}
}
}
}
}
如果在您的情况下,如果您希望允许网格覆盖剩余的LazyColumn高度,您可以测量其他元素的高度,并使用Modifier.height(parent height - 其他内容的高度之和),这实际上非常容易通过自定义的Layout来实现。
如果您好奇为什么会出现此异常,那是因为滚动代码中在设置具有滚动修饰符的组合之前进行了检查。
private class ScrollingLayoutNode(
var scrollerState: ScrollState,
var isReversed: Boolean,
var isVertical: Boolean
) : LayoutModifierNode, Modifier.Node() {
override fun MeasureScope.measure(
measurable: Measurable,
constraints: Constraints
): MeasureResult {
checkScrollableContainerConstraints(
constraints,
if (isVertical) Orientation.Vertical else Orientation.Horizontal
)
val childConstraints = constraints.copy(
maxHeight = if (isVertical) Constraints.Infinity else constraints.maxHeight,
maxWidth = if (isVertical) constraints.maxWidth else Constraints.Infinity
)
val placeable = measurable.measure(childConstraints)
val width = placeable.width.coerceAtMost(constraints.maxWidth)
val height = placeable.height.coerceAtMost(constraints.maxHeight)
val scrollHeight = placeable.height - height
val scrollWidth = placeable.width - width
val side = if (isVertical) scrollHeight else scrollWidth
}
而且,
checkScrollableContainerConstraints
函数是什么。
fun checkScrollableContainerConstraints(
constraints: Constraints,
orientation: Orientation
) {
if (orientation == Orientation.Vertical) {
check(constraints.maxHeight != Constraints.Infinity) {
"Vertically scrollable component was measured with an infinity maximum height " +
"constraints, which is disallowed. One of the common reasons is nesting layouts " +
"like LazyColumn and Column(Modifier.verticalScroll()). If you want to add a " +
"header before the list of items please add a header as a separate item() before " +
"the main items() inside the LazyColumn scope. There are could be other reasons " +
"for this to happen: your ComposeView was added into a LinearLayout with some " +
"weight, you applied Modifier.wrapContentSize(unbounded = true) or wrote a " +
"custom layout. Please try to remove the source of infinite constraints in the " +
"hierarchy above the scrolling container."
}
} else {
check(constraints.maxWidth != Constraints.Infinity) {
"Horizontally scrollable component was measured with an infinity maximum width " +
"constraints, which is disallowed. One of the common reasons is nesting layouts " +
"like LazyRow and Row(Modifier.horizontalScroll()). If you want to add a " +
"header before the list of items please add a header as a separate item() before " +
"the main items() inside the LazyRow scope. There are could be other reasons " +
"for this to happen: your ComposeView was added into a LinearLayout with some " +
"weight, you applied Modifier.wrapContentSize(unbounded = true) or wrote a " +
"custom layout. Please try to remove the source of infinite constraints in the " +
"hierarchy above the scrolling container."
}
}
}
LazyColumn
的性能要低得多。此外,您是否尝试过具有相同布局的普通单元格LazyColumn
?我认为我的方法对于普通的LazyColumn
来说并不会增加太多开销。 - Phil DukhovLazyVerticalGrid
应该比我的解决方案表现更好,因为自从**1.2.*版本开始,它已经被重写,不再使用LazyColumn
。但是在1.1.***版本中,我预计性能大致相同。 - Phil Dukhov