簡體   English   中英

LazyColumn 內的 LazyHorizontalGrid

[英]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))
                    }
                }
            }
        }
    }
}

當您嘗試使用Constraints.Infinity測量相應維度時,會出現帶有維度的LazyList異常。 在這個答案中解釋了如何基於修飾符Modifier.scroll()應用約束。 此外,使用像LazyColumn這樣的可滾動父 Composable 創建具有無限高度的 Constraints, LazyRow創建具有無限寬度的 Constraints。

您可以將 Modifier.height(maxHeight) 與 maxHeight 從

您可以使用Modifier.height(maxHeight)Modifier.layout{}並將最大高度限制為屏幕高度或以像素為單位的選定高度。 約束返回將與布局 function 一起使用的以 px 為單位的尺寸。通過用 BoxWithConstraints 包裝它從父級獲取約束高度返回非無限高度

@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
                           // .height(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.onSizeChanged 或在此答案中使用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)
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM