I want to achieve a “dynamic” height LazyVerticalGrid meaning the height of one item in the row dete...
i
I want to achieve a “dynamic” height LazyVerticalGrid meaning the height of one item in the row determines the height of the rest to avoid the effect of the image. The only “clean” way is to ditch the Grid and make a LazyColumn with a Row as each item?!! I know the other option would be to hard code the same height for every item in the grid, but that would produce (maybe) an unwanted space between rows. The code to produce the example is simple but it’s added in the thread
❤️ 1
Copy code
@Composable
fun TestItem(countText: Int ) {
    Column(modifier = Modifier
        .padding(16.dp)
        .background(Color.Red)
    ) {
        Box(
            modifier = Modifier
                .background(Color.Blue)
                .height(128.dp)
                .fillMaxWidth()
        )
        Spacer(modifier = Modifier.weight(1f))
        repeat(countText) {
            Text(
                text = "This is a line",
            )
        }
    }
}
Item
usage
Copy code
LazyVerticalGrid(
    cells = GridCells.Fixed(2),
) {
    item {
        TestItem(1)
    }
    item {
        TestItem(4)
    }
}
r
Setting
Modifier.aspectRatio(1f)
to the
TestItem
Column
should work!
i
but that would just make it square, wouldn’t it?
r
Oh true, nvm What about using
SubcomposeLayout
to measure each item, get the highest one, "return it" and set that height to each item?
i
Hmm, that’s sound more interesting! I haven’t worked with it yet. Do you have any links about it or guidance?
r
Yes! Faced this myself and I was trying to find out a solution, unluckily it's been a long time since I've done anything so I don't remember much rn but this is the post I came across in the past, pretty sure it will help you as a baseline at least https://stackoverflow.com/a/73595634
I can't remember what I did in the past to measure each item, but I know there's a way around that, that example might not fit your needs*
This one might be better, I remember paying more attention to this specific example: https://stackoverflow.com/a/70383694
This is an example that would fill your main request so there you go, it might help you to dig a bit and use it as a playground and evolve from there! I was playing around to refresh some knowledge and save the example for the future, hope it helps!
Copy code
data class UiModel(val lines: Int)

@Composable
private fun MyCoolGrid(list: List<UiModel>) {

    SubcomposeLayout { constraints ->
        val measuredHeights = subcompose(SlotsEnum.Height) {
            list.map { TestItem(countText = it.lines, minHeight = 0.dp) }
        }.map {
            val measure = it.measure(constraints)
            val measuredHeight = measure.measuredHeight.toDp()
            logD("measuredheight $measuredHeight")
            measuredHeight
        }
        val maxHeight = measuredHeights.maxOrNull() ?: 0.dp // get the max height from all items!!

        // Measure the LazyVerticalGrid
        val contentPlaceable = subcompose(SlotsEnum.Content) {
            LazyVerticalGrid(
                modifier = Modifier,
                columns = GridCells.Fixed(2),
            ) {
                itemsIndexed(list) { index, item ->
                    TestItem(
                        text = "$maxHeight",
                        countText = item.lines,
                        minHeight = maxHeight // We are setting the max height to each item!!
                    )
                }
            }
        }.first().measure(constraints)

        logD("Whole LazyVerticalGrid component measured ${contentPlaceable.measuredHeight.toDp()}")
        layout(contentPlaceable.width, contentPlaceable.height) {
            // Place the LazyVerticalGrid with its content
            contentPlaceable.place(0, 0)
        }
    }
}

private fun logD(text: String) {
    Log.d("SomeCoolGrid", "$text")
}

private enum class SlotsEnum {
    Height, Width, Content // You could also measure Width
}

@Composable
fun TestItem(text: String = "This is a line", countText: Int, minHeight: Dp = 0.dp) {
    Column(
        modifier = Modifier
            .defaultMinSize(minHeight = minHeight)
            .padding(horizontal = 16.dp, vertical = 16.dp)
            .background(Color.Red)

    ) {
        Box(
            modifier = Modifier
                .background(Color.Blue)
                .height(128.dp)
                .fillMaxWidth()
        )
//        Spacer(modifier = Modifier.weight(1f))
        repeat(countText) {
            Text(
                text = "$text",
            )
        }
    }
}
3722 Views