Equal size tiles

Custom layout to constraint and place children in slots of equal dimensions using a single measure pass

@Composable
fun EqualSizeTiles(
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit,
) {
    Layout(
        content = content,
        modifier = modifier,
    ) { measurables, constraints ->
        layoutTiles(
            measurables,
            constraints
        )
    }
}

private fun MeasureScope.layoutTiles(
    measurables: List<Measurable>,
    constraints: Constraints,
): MeasureResult {
    val tileHeight = constraints.maxHeight
    val tileWidths = measurables.map { measurable ->
        measurable.maxIntrinsicWidth(tileHeight)
    }
    val tileWidth = tileWidths.maxOrNull() ?: 0
    val tileConstraints = Constraints(
        minWidth = tileWidth,
        minHeight = 0,
        maxWidth = tileWidth,
        maxHeight = constraints.maxHeight,
    )
    val placeables = measurables.map { measurable ->
        measurable.measure(tileConstraints)
    }
    val width = (placeables.size * tileWidth).coerceAtMost(constraints.maxWidth)
    return layout(width = width, height = tileHeight) {
        placeables.forEachIndexed { index, placeable ->
            placeable.place(tileWidth * index, 0)
        }
    }
}

@Preview(showBackground = true)
@Composable
private fun EqualSizeTilesPreview() {
    WeatherSampleTheme {
        Surface(modifier = Modifier
            .width(512.dp)
            .background(color = Color.Yellow)) {
            EqualSizeTiles(
                modifier = Modifier
                    .height(64.dp)
                    .background(color = Color.Green)
                    .padding(all = 8.dp)
            ) {
                Text(
                    text = "Left",
                    textAlign = TextAlign.Center,
                    modifier = Modifier
                        .background(color = Color.Red)
                        .padding(all = 8.dp)
                        .fillMaxHeight(),
                )
                Text(
                    text = "Center",
                    textAlign = TextAlign.Center,
                    modifier = Modifier
                        .background(color = Color.Yellow)
                        .padding(all = 8.dp)
                        .fillMaxHeight(),
                )
                Text(
                    text = "Right element",
                    textAlign = TextAlign.Center,
                    modifier = Modifier
                        .background(color = Color.Blue)
                        .padding(all = 8.dp)
                        .fillMaxHeight(),
                )
            }
        }
    }
}

Have a project you'd like to submit? Fill this form, will ya!

If you like this snippet, you might also like:

Maker OS is an all-in-one productivity system for developers

I built Maker OS to track, manage & organize my life. Now you can do it too!