Last active
September 1, 2024 19:19
-
-
Save vganin/081b535f0c21b6fcf43c7a71bde91bdd to your computer and use it in GitHub Desktop.
[DEPRECATED, use official FlowRow instead] Jetpack Compose simple flex-wrap container
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Composable | |
fun FlowRow( | |
horizontalGap: Dp = 0.dp, | |
verticalGap: Dp = 0.dp, | |
alignment: Alignment.Horizontal = Alignment.Start, | |
content: @Composable () -> Unit, | |
) = Layout(content = content) { measurables, constraints -> | |
val horizontalGapPx = horizontalGap.toPx().roundToInt() | |
val verticalGapPx = verticalGap.toPx().roundToInt() | |
val rows = mutableListOf<Row>() | |
var rowConstraints = constraints | |
var rowPlaceables = mutableListOf<Placeable>() | |
measurables.forEach { measurable -> | |
val placeable = measurable.measure(Constraints()) | |
if (placeable.measuredWidth !in rowConstraints.minWidth..rowConstraints.maxWidth) { | |
rows += Row(rowPlaceables, horizontalGapPx) | |
rowConstraints = constraints | |
rowPlaceables = mutableListOf() | |
} | |
val consumedWidth = placeable.measuredWidth + horizontalGapPx | |
rowConstraints = rowConstraints.offset(horizontal = -consumedWidth) | |
rowPlaceables.add(placeable) | |
} | |
rows += Row(rowPlaceables, horizontalGapPx) | |
val width = constraints.maxWidth | |
val height = (rows.sumBy { row -> row.height } + (rows.size - 1) * verticalGapPx) | |
.coerceAtMost(constraints.maxHeight) | |
layout(width, height) { | |
var y = 0 | |
rows.forEach { row -> | |
val offset = alignment.align(row.width, width, layoutDirection) | |
var x = offset | |
row.placeables.forEach { placeable -> | |
placeable.placeRelative(x, y) | |
x += placeable.width + horizontalGapPx | |
} | |
y += row.height + verticalGapPx | |
} | |
} | |
} | |
private class Row( | |
val placeables: List<Placeable>, | |
val horizontalGapPx: Int, | |
) { | |
val width by lazy(mode = LazyThreadSafetyMode.NONE) { | |
placeables.sumBy { it.width } + (placeables.size - 1) * horizontalGapPx | |
} | |
val height by lazy(mode = LazyThreadSafetyMode.NONE) { | |
placeables.maxOfOrNull { it.height } ?: 0 | |
} | |
} | |
@Composable | |
private fun Preview(alignment: Alignment.Horizontal) { | |
Box(Modifier.width(100.dp)) { | |
FlowRow( | |
horizontalGap = 8.dp, | |
verticalGap = 8.dp, | |
alignment = alignment, | |
) { | |
repeat(17) { index -> | |
Text(text = index.toString()) | |
} | |
} | |
} | |
} | |
@Preview | |
@Composable | |
private fun PreviewAlignStart() = Preview(alignment = Alignment.Start) | |
@Preview | |
@Composable | |
private fun PreviewAlignCenter() = Preview(alignment = Alignment.CenterHorizontally) | |
@Preview | |
@Composable | |
private fun PreviewAlignEnd() = Preview(alignment = Alignment.End) |
https://developer.android.com/develop/ui/compose/layouts/flow
Dropping link for now available official support in compose.
https://developer.android.com/develop/ui/compose/layouts/flow Dropping link for now available official support in compose.
Thanks! I'll update the description with the pointer towards official implementation.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I want to say that I am highly grateful to you for this solution. I spent over 8hrs looking for a custom wrap widget in Compose not untill I found your repo. Thank you very much for building this solution.