Sarbyn
Sarbyn

Reputation: 340

Compose Row with wrong height

I have a strange behaviour with jetpack compose row. This is the demo code: display a row with X items and a vertical divider. Colors are for demo purpose :)

@Composable
fun StackOverflowDemo(itemList: List<Int>) {
    Row(
        modifier = Modifier
            .height(IntrinsicSize.Min)
            .background(Color.Blue)
            .horizontalScroll(rememberScrollState())
    ) {
        itemList.forEach {
            Text(
                it.toString(),
                modifier = Modifier
                    .background(Color.Yellow)
                    .padding(horizontal = 4.dp)

            )
            Divider(
                color = Color.Red,
                modifier = Modifier
                    .width(1.dp)
                    .fillMaxHeight()
            )
        }
    }
}

With few elements (10), this is the result

Short list

But with more elements (30), the result is wrong: the row height is not equal to the single item height, and the vertical divider is too high

Long list

Why there is such a different behaviour? What is missing in this simple setup?

Upvotes: 2

Views: 646

Answers (1)

nglauber
nglauber

Reputation: 23894

If you need a emergency workaround, you can use SubcomposeLayout in order to calculate the max height and use it as Divider height.

@Composable
fun StackOverflowDemo(itemList: List<Int>) {
    Box(
        Modifier
            .background(Color.Blue)
            .horizontalScroll(rememberScrollState())
    ) {
        SubcomposeLayout { constraints ->
            // Measuring each Text
            val placeables = subcompose("SomeRandomId") {
                itemList.forEach {
                    Text(
                        it.toString(),
                        modifier = Modifier
                            .background(Color.Yellow)
                            .padding(horizontal = 4.dp)
                    )
                }
            }.map { it.measure(constraints) }

            // Getting the max height to use in the divider
            val maxHeight = placeables.maxOf { it.height }

            // Now the Dividers are measured
            val dividers = subcompose("SomeDividerId") {
                (0 until itemList.lastIndex).map {
                    Divider(
                        color = Color.Red,
                        modifier = Modifier
                            .height(with(LocalDensity.current) { maxHeight / density }.dp)
                            .width(1.dp)
                    )
                }
            }.map { it.measure(constraints) }

            // Calculating the total width of the components
            val width = placeables.sumOf { it.width } + dividers.sumOf { it.width }

            // Placing Text and dividers into the layout
            layout(width, maxHeight) {
                var x = 0
                placeables.forEachIndexed { index, placeable ->
                    placeable.placeRelative(x, 0)
                    x += placeable.width
                    // the divider is not displayed after the last item
                    if (index < placeables.lastIndex) {
                        dividers[index].place(x, 0)
                        x += dividers[index].width
                    }
                }
            }
        }
    }
}

Here's the result:

enter image description here

Upvotes: 1

Related Questions