You can use SubcomposeLayout to pass a Composable's dimension if another one depends on it without recomposition or in your case even if it's not even in composition.
@Composable
internal fun DimensionSubcomposeLayout(
modifier: Modifier = Modifier,
mainContent: @Composable () -> Unit,
dependentContent: @Composable (DpSize) -> Unit
) {
val density = LocalDensity.current
SubcomposeLayout(
modifier = modifier
) { constraints: Constraints ->
// Subcompose(compose only a section) main content and get Placeable
val mainPlaceable: Placeable = subcompose(SlotsEnum.Main, mainContent)
.map {
it.measure(constraints.copy(minWidth = 0, minHeight = 0))
}.first()
val dependentPlaceable: Placeable =
subcompose(SlotsEnum.Dependent) {
dependentContent(
DpSize(
density.run { mainPlaceable.width.toDp() },
density.run { mainPlaceable.height.toDp() }
)
)
}
.map { measurable: Measurable ->
measurable.measure(constraints)
}.first()
layout(mainPlaceable.width, mainPlaceable.height) {
dependentPlaceable.placeRelative(0, 0)
}
}
}
/**
* Enum class for SubcomposeLayouts with main and dependent Composables
*/
enum class SlotsEnum { Main, Dependent }
And you can use it to set dimensions of Box based on measuring or subcomposing your Button.
@Composable
private fun DimensionSample() {
var componentVisible1 by remember { mutableStateOf(false) }
var component2Visible by remember { mutableStateOf(true) }
Column {
Button(onClick = {
componentVisible1 = !componentVisible1
component2Visible = !component2Visible
}) {
Text(text = "Toggle")
}
val button = @Composable {
Button(
modifier = Modifier
.height(48.dp)
.widthIn(144.dp),
onClick = {}
) {
Text(
text = "text1",
)
}
}
val circularProgressIndicator = @Composable {
CircularProgressIndicator(
modifier = Modifier
.size(24.dp)
.background(Color.Yellow, CircleShape)
.padding(2.dp),
strokeWidth = 2.dp
)
}
DimensionSubcomposeLayout(mainContent = {
button()
}) {
Box(
modifier = Modifier
.size(it)
.then(Modifier.background(Color.Red)),
contentAlignment = Alignment.Center
) {
if (componentVisible1) {
button()
}
if (component2Visible) {
circularProgressIndicator()
}
}
}
}
}
