Skip to content

Instantly share code, notes, and snippets.

@cbeyls
Created September 17, 2020 00:30
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cbeyls/66142cc04348d8246475b730aabef701 to your computer and use it in GitHub Desktop.
Save cbeyls/66142cc04348d8246475b730aabef701 to your computer and use it in GitHub Desktop.
FlowLayout implementation for Jetpack Compose
package be.digitalia.compose.layout
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Layout
import androidx.compose.ui.Modifier
@Composable
fun FlowLayout(
modifier: Modifier = Modifier,
rowHorizontalGravity: Alignment.Horizontal = Alignment.Start,
childVerticalGravity: Alignment.Vertical = Alignment.Top,
children: @Composable () -> Unit
) {
class RowInfo(val width: Int, val height: Int, val nextChildIndex: Int)
Layout(
children = children,
modifier = modifier
) { measurables, constraints ->
var contentWidth = 0
var contentHeight = 0
var rowWidth = 0
var rowHeight = 0
val rows = mutableListOf<RowInfo>()
val maxWidth = constraints.maxWidth
val childConstraints = constraints.copy(minWidth = 0, minHeight = 0)
val placeables = measurables.mapIndexed { index, measurable ->
measurable.measure(childConstraints).also { placeable ->
val newRowWidth = rowWidth + placeable.width
if (newRowWidth > maxWidth) {
rows.add(RowInfo(width = rowWidth, height = rowHeight, nextChildIndex = index))
contentWidth = maxOf(contentWidth, rowWidth)
contentHeight += rowHeight
rowWidth = placeable.width
rowHeight = placeable.height
} else {
rowWidth = newRowWidth
rowHeight = maxOf(rowHeight, placeable.height)
}
}
}
rows.add(RowInfo(width = rowWidth, height = rowHeight, nextChildIndex = measurables.size))
contentWidth = maxOf(contentWidth, rowWidth)
contentHeight += rowHeight
layout(
width = maxOf(contentWidth, constraints.minWidth),
height = maxOf(contentHeight, constraints.minHeight)
) {
var childIndex = 0
var y = 0
rows.forEach { rowInfo ->
var x = rowHorizontalGravity.align(parentWidth - rowInfo.width)
val rowHeight = rowInfo.height
val nextChildIndex = rowInfo.nextChildIndex
while (childIndex < nextChildIndex) {
val placeable = placeables[childIndex]
placeable.placeRelative(
x = x,
y = y + childVerticalGravity.align(rowHeight - placeable.height)
)
x += placeable.width
childIndex++
}
y += rowHeight
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment