Created
May 21, 2022 18:48
-
-
Save Pepijn98/3ed6af2e8d8a43845cc0d9da9c3a3da0 to your computer and use it in GitHub Desktop.
Vertical grid with staggered items (does not lazily load items)
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
package dev.vdbroek.nekos.components | |
/** | |
* Original source: https://github.com/android/compose-samples/blob/1630f6b35ac9e25fb3cd3a64208d7c9afaaaedc5/Owl/app/src/main/java/com/example/owl/ui/courses/FeaturedCourses.kt#L161 | |
*/ | |
import androidx.compose.runtime.Composable | |
import androidx.compose.ui.Modifier | |
import androidx.compose.ui.layout.Layout | |
import androidx.compose.ui.unit.Dp | |
import kotlin.math.ceil | |
@Composable | |
fun StaggeredVerticalGrid( | |
modifier: Modifier = Modifier, | |
maxColumnWidth: Dp, | |
content: @Composable () -> Unit | |
) { | |
Layout( | |
content = content, | |
modifier = modifier | |
) { measurables, constraints -> | |
check(constraints.hasBoundedWidth) { | |
"Unbounded width not supported" | |
} | |
val columns = ceil(constraints.maxWidth / maxColumnWidth.toPx()).toInt() | |
val columnWidth = constraints.maxWidth / columns | |
val itemConstraints = constraints.copy(minWidth = 0, maxWidth = columnWidth) | |
val colHeights = IntArray(columns) { 0 } // track each column's height | |
val placeables = measurables.map { measurable -> | |
val column = shortestColumn(colHeights) | |
val placeable = measurable.measure(itemConstraints) | |
colHeights[column] += placeable.height | |
placeable | |
} | |
val height = colHeights.maxOrNull()?.coerceIn(constraints.minHeight, constraints.maxHeight) ?: constraints.minHeight | |
layout( | |
width = constraints.maxWidth, | |
height = height | |
) { | |
val colY = IntArray(columns) { 0 } | |
placeables.forEach { placeable -> | |
val column = shortestColumn(colY) | |
placeable.place( | |
x = columnWidth * column, | |
y = colY[column] | |
) | |
colY[column] += placeable.height | |
} | |
} | |
} | |
} | |
private fun shortestColumn(colHeights: IntArray): Int { | |
var minHeight = Int.MAX_VALUE | |
var column = 0 | |
colHeights.forEachIndexed { index, height -> | |
if (height < minHeight) { | |
minHeight = height | |
column = index | |
} | |
} | |
return column | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment