Timo Drick
03/12/2025, 8:57 AMZach Klippenstein (he/him) [MOD]
03/12/2025, 3:11 PMTimo Drick
03/12/2025, 5:24 PMTimo Drick
03/12/2025, 5:29 PM@Composable
fun SmartScrollableFlowRow(
modifier: Modifier = Modifier,
horizontalPadding: Dp = 4.dp,
verticalPadding: Dp = 4.dp,
scrollState: ScrollState,
content: @Composable () -> Unit
) {
Layout(
modifier = modifier.horizontalScroll(scrollState),
content = {
content()
},
) { measurables, constraints ->
val paddingX = horizontalPadding.roundToPx()
val paddingY = verticalPadding.roundToPx()
var largestChildWidth = 0
val placeables = measurables.map { measurable ->
val placeable = measurable.measure(constraints)
largestChildWidth = max(largestChildWidth, placeable.width)
placeable
}
val width = max(scrollState.viewportSize, largestChildWidth)
var posX = 0
var posY = 0
var maxRowHeight = 0
var maxRowWidth = 0
var heightSum = 0
val offset = placeables.map {
if (posX > 0 && (posX + it.width) > width) {
//Next row
posX = 0
posY += paddingY + maxRowHeight
maxRowHeight = 0
}
val pos = IntOffset(posX, posY)
maxRowHeight = max(maxRowHeight, it.height)
maxRowWidth = max(maxRowWidth, posX + it.width)
heightSum = posY + it.height
posX += it.width + paddingX
pos
}
layout(maxRowWidth, heightSum) {
placeables.forEachIndexed { index, placeable ->
placeable.place(offset[index])
}
}
}
}
Timo Drick
03/12/2025, 6:35 PMTimo Drick
03/13/2025, 11:50 PMfun Modifier.intrinsicScrollModifier(scrollState: ScrollState) = horizontalScroll(scrollState) then object : LayoutModifier {
override fun MeasureScope.measure(
measurable: Measurable,
constraints: Constraints
): MeasureResult {
val intrinsic = measurable.minIntrinsicWidth(constraints.maxHeight)
val maxViewport = max(constraints.minWidth, scrollState.viewportSize)
val innerConstraints = constraints.copy(
maxWidth = max(maxViewport, intrinsic)
)
val placeable = measurable.measure(innerConstraints)
val width = max(placeable.width, intrinsic)
return layout(width, placeable.height) {
placeable.place(0, 0)
}
}
}
Timo Drick
03/13/2025, 11:51 PMTimo Drick
03/13/2025, 11:51 PMval scrollState = rememberScrollState()
FlowRow(
modifier = Modifier.fillMaxWidth()
.intrinsicScrollModifier(scrollState)
) {
repeat(5) {
Text(
modifier = Modifier.requiredSize(180.dp, 50.dp)
.background(Color.LightGray),
text = "Test $it"
)
}
}