jordond
07/26/2024, 12:26 AMScaleLayout {}
that will scale the content in {}
to fit the max height available.
What I have seems to work, but I just want to make sure i’m not doing something terribly wrong.jordond
07/26/2024, 12:26 AM@Composable
fun ScaledLayout(
modifier: Modifier = Modifier,
content: @Composable BoxWithConstraintsScope.() -> Unit,
) {
BoxWithConstraints(modifier = modifier) {
val constraints = this@BoxWithConstraints.constraints
SubcomposeLayout { layoutConstraints ->
val contentPlaceables = subcompose(slotId = "content") { content() }
.map { measurable ->
val value = Constraints(
maxWidth = layoutConstraints.maxWidth,
maxHeight = Constraints.Infinity,
)
measurable.measure(value)
}
val contentHeight = contentPlaceables.maxOfOrNull { it.height }?.toFloat() ?: 0f
val maxHeight = constraints.maxHeight.toFloat()
val scale = if (contentHeight > 0) maxHeight / contentHeight else 1f
val scaledWidth = ((contentPlaceables.maxOfOrNull { it.width } ?: (0 * scale))).toInt()
val offsetX = (constraints.maxWidth - scaledWidth) / 2
val offsetY = (constraints.maxHeight - contentHeight) / 2
layout(constraints.maxWidth, constraints.maxHeight) {
contentPlaceables.forEach { placeable ->
placeable.placeRelativeWithLayer(
offsetX,
offsetY.toInt()
) {
scaleX = scale
scaleY = scale
}
}
}
}
}
}
Albert Chang
07/26/2024, 2:38 AMjordond
07/26/2024, 3:27 PMAlbert Chang
07/27/2024, 7:29 AM@Composable
fun ScaledLayout(
modifier: Modifier = Modifier,
content: @Composable BoxScope.() -> Unit,
) {
Layout(
content = { Box(content = content) },
modifier = modifier,
) { measurables, constraints ->
val placeable = measurables.single()
.measure(Constraints(maxWidth = constraints.maxWidth))
val scale = if (placeable.height > 0) {
constraints.maxHeight.toFloat() / placeable.height
} else {
1f
}
layout(constraints.maxWidth, constraints.maxHeight) {
placeable.placeRelativeWithLayer(
(constraints.maxWidth - placeable.width) / 2,
(constraints.maxHeight - placeable.height) / 2,
) {
scaleX = scale
scaleY = scale
}
}
}
}
Albert Chang
07/27/2024, 7:35 AMSubcomposeLayout
(including BoxWithConstraints
) is less performant than regular Layout
so you should avoid it when possible. Basically you only need SubcomposeLayout
if:
• You need the incoming constraints (layout size etc.) when you compose the children
• You need the measured size of some other children when you compose the children
• You need the incoming constraints and/or the measured size of some other children to decide whether to compose some children
You don't need SubcomposeLayout
if you need the incoming constraints and/or the measured size of some other children when you measure and layout the children.jordond
07/27/2024, 10:01 PM