LazyHorizontalGrid inside LazyColumn



我有一个LazyColumn和里面我想显示一个水平行与两列,所以我尝试LazyHorizontalGrid来实现它。但是我的应用程序崩溃了,例外-IllegalArgumentException: LazyHorizontalGrid's height should be bound by parent。下面是我的代码,我正在使用,谁可以帮助修复它或任何其他方式,通过它,我可以使一行有两列。

@Composable
fun HomeItem1() {
Surface(modifier = Modifier.nestedScroll(rememberViewInteropNestedScrollConnection())) {
LazyColumn {
//other contents
item {
LazyHorizontalGrid(
rows = GridCells.Fixed(3),
horizontalArrangement = Arrangement.spacedBy(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
items(arrayList.size) {
Text(arrayList[it])
}
}
}
}
}
}

你只需要事先计算网格的高度。

@Composable
fun HomeItem1() {
Surface(modifier = Modifier.nestedScroll(rememberViewInteropNestedScrollConnection())) {
LazyColumn {
//other contents
item {
LazyHorizontalGrid(
modifier = Modifier.height(176.dp), // itemHeight * rowCount + verticalSpacing * (rowCount - 1)
rows = GridCells.Fixed(3),
horizontalArrangement = Arrangement.spacedBy(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
items(arrayList.size) {
Text(arrayList[it], modifier = Modifier.height(48.dp))
}
}
}
}
}
}

LazyListexceptionsand dimensions当您尝试用Constraints.Infinity测量各自的尺寸时发生。我在这个回答中解释了如何基于修饰符Modifier.scroll()应用约束。此外,使用可滚动的父组件(如LazyColumn)创建具有无限高度的约束LazyRow创建无限宽度约束.

你可以使用modifier .height (maxHeight)与maxHeight,这意味着这个LazyColumn可以被测量或分配父元素的总高度最多,如果总和的内容高度大于其他项目没有使用的高度。

你可以使用Modifier.heightIn(maxHeight)Modifier.layout{},并将最大高度约束为屏幕高度或选定的高度在px。约束返回尺寸,单位为px,用于布局函数。通过使用BoxWithConstraints包装从父元素获取constraints高度,返回非无限的高度

@Composable
private fun Sample() {
val arrayList = remember {
mutableStateListOf<String>().apply {
repeat(40) {
add("Item $it")
}
}
}

Column(
modifier = Modifier
.border(4.dp, Color.Green)
.fillMaxSize()
) {
BoxWithConstraints {
val parentConstraints = this.constraints
val maxHeight = this.maxHeight
LazyColumn {
//other contents
item {
Image(
modifier = Modifier
.height(200.dp)
.fillMaxWidth(),
painter = painterResource(id = R.drawable.landscape2),
contentDescription = null,
contentScale = ContentScale.FillBounds
)
}
item {
LazyHorizontalGrid(
modifier = Modifier
.border(2.dp, Color.Red)
// Alternative 1
// .heightIn(maxHeight)
// Alternative 2
.layout { measurable, constraints ->
val placeable = measurable.measure(
constraints.copy(maxHeight = parentConstraints.maxHeight)
)
layout(placeable.width, placeable.height) {
placeable.placeRelative(0, 0)
}
},
rows = GridCells.Fixed(3),
horizontalArrangement = Arrangement.spacedBy(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
items(arrayList.size) {
Box(
modifier = Modifier
.shadow(2.dp, RoundedCornerShape(8.dp))
.background(Color.White)
.aspectRatio(1f)
.padding(2.dp)
) {
Text(arrayList[it])
}
}
}
}
}
}
}
}

上面的例子创建了一个LazyHorizontalGrid与屏幕的全部高度,我添加了一个Image作为另一个元素来显示网格覆盖父高度。

这里重要的是如何为 中的Constraints设置maxHeight
constraints.copy(maxHeight = parentConstraints.maxHeight)

如果你想让网格匹配项目的大小,那么你应该测量项目的大小

使用rowCount * itemHeight + (rowCount-1)* verticalSpacingInPx.

例如constraints.copy(maxHeight = 600f)

如果你不知道项目的高度,你应该使用Modifier。

onsizechange或SubcomposeLayoutLayout

如何在不重组的情况下获得准确的尺寸?

使用Text作为依赖项我们可以设置为

@Composable
private fun Sample2() {
val arrayList = remember {
mutableStateListOf<String>().apply {
repeat(40) {
add("Item $it")
}
}
}
val mainComposable = @Composable {
Box(
modifier = Modifier
.shadow(2.dp, RoundedCornerShape(8.dp))
.background(Color.White)
.size(80.dp)
.padding(2.dp)
) {
Text(arrayList[0])
}
}
Column(
modifier = Modifier
.border(4.dp, Color.Green)
.fillMaxSize()
) {
DimensionSubcomposeLayout(
rowCount = 3,
verticalSpacing = 16.dp,
mainContent = {
mainComposable()
}
) { size: Dp ->
LazyColumn {
//other contents
item {
Image(
modifier = Modifier
.height(200.dp)
.fillMaxWidth(),
painter = painterResource(id = R.drawable.landscape2),
contentDescription = null,
contentScale = ContentScale.FillBounds
)
}
item {
LazyHorizontalGrid(
modifier = Modifier
.height(size)
.border(2.dp, Color.Red),
rows = GridCells.Fixed(3),
horizontalArrangement = Arrangement.spacedBy(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
items(arrayList.size) {
Box(
modifier = Modifier
.shadow(2.dp, RoundedCornerShape(8.dp))
.background(Color.White)
.size(80.dp)
.padding(2.dp)
) {
Text(arrayList[it])
}
}
}
}
}
}
}
}

使用文本高度和间距来计算LazyHorizontal Grid的高度的SubComposeLayout

@Composable
fun DimensionSubcomposeLayout(
modifier: Modifier = Modifier,
rowCount: Int,
verticalSpacing: Dp = 0.dp,
mainContent: @Composable () -> Unit,
dependentContent: @Composable (Dp) -> Unit
) {
val density = LocalDensity.current
val verticalSpacingPx = density.run { verticalSpacing.toPx() }
SubcomposeLayout(
modifier = modifier
) { constraints: Constraints ->
// Subcompose(compose only a section) main content and get Placeable
val mainPlaceable = subcompose(SlotsEnum.Main, mainContent)
.map {
it.measure(constraints)
}
.first()

// Get max width and height of main component
val maxHeight = mainPlaceable.height * rowCount + (rowCount - 1) * verticalSpacingPx
val dpSize = with(density.density) {
maxHeight.toDp()
}
val dependentPlaceable = subcompose(SlotsEnum.Dependent) {
dependentContent(dpSize)
}
.map { measurable: Measurable ->
measurable.measure(constraints)
}
.first()
layout(dependentPlaceable.width, dependentPlaceable.height) {
dependentPlaceable.placeRelative(0, 0)
}
}
}

为LazyHorizontalGrid设置一个固定的高度或最大高度。

@Composable
fun HomeItem1() {
Surface(modifier = Modifier.nestedScroll(rememberViewInteropNestedScrollConnection())) {
LazyColumn {
//other contents
item {
LazyHorizontalGrid(
modifier = Modifier.heightIn(max=200.dp),
rows = GridCells.Fixed(3),
horizontalArrangement = Arrangement.spacedBy(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
items(arrayList.size) {
Text(arrayList[it])
}
}
}
}
}
}

如果高度增加超过200。dp,然后网格将开始嵌套滚动。如果你真的想确保你不想要嵌套的滚动,使用"丑"解决方法是设置一个非常大的最大高度。

相关内容

  • 没有找到相关文章

最新更新