https://kotlinlang.org logo
#codereview
Title
# codereview
m

Mark

11/16/2023, 8:09 AM
Custom layout that behaves like a column but fixes the width equal to the first item width. This is my first custom layout, so I’m wondering about ways to improve, or whether it can be done without a custom layout in the first place.
Copy code
@Composable
fun LayoutItemsVerticallyWrappingFirstWidth(
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit,
) {
    Layout(
        content = content,
        modifier = modifier,
    ) { measurables, constraints ->
        val firstItem = measurables.firstOrNull()
            ?: return@Layout layout(
                width = constraints.minWidth,
                height = constraints.minHeight,
            ) { }
        val firstItemWidth = firstItem.maxIntrinsicWidth(constraints.maxHeight)
        val itemConstraints = Constraints(
            minWidth = 0,
            minHeight = 0,
            maxWidth = firstItemWidth,
            maxHeight = constraints.maxHeight,
        )
        val placeables = measurables.map { measurable ->
            measurable.measure(itemConstraints)
        }
        val height = placeables
            .sumOf(Placeable::height)
            .coerceAtMost(constraints.maxHeight)
        layout(width = firstItemWidth, height = height) {
            var yOffset = 0
            placeables.forEach { placeable ->
                val xOffset = (firstItemWidth - placeable.width) / 2
                placeable.place(xOffset, yOffset)
                yOffset += placeable.height
            }
        }
    }
}
👀 1
For testing:
Copy code
@Preview(showBackground = true)
@Composable
private fun LayoutItemsVerticallyPreview() {
    LayoutItemsVerticallyWrappingFirstWidth(
        modifier = Modifier.background(Color.Yellow),
    ) {
        Text(
            text = "first item",
            overflow = TextOverflow.Ellipsis,
            maxLines = 1,
            modifier = Modifier.background(Color.Green),
        )
        Text(
            text = "longer item",
            overflow = TextOverflow.Ellipsis,
            maxLines = 1,
            modifier = Modifier.background(Color.Red),
        )
        Text(
            text = "short",
            overflow = TextOverflow.Ellipsis,
            maxLines = 1,
            modifier = Modifier.background(Color.Blue),
        )
    }
}