{% setvar book_path %}/reference/androidx/_book.yaml{% endsetvar %} {% include "_shared/_reference-head-tags.html" %}

SubcomposeLayoutKt

public final class SubcomposeLayoutKt


Summary

Public methods

static final void

Analogue of Layout which allows to subcompose the actual content during the measuring stage for example to use the values calculated during the measurement as params for the composition of the children.

static final void

Analogue of Layout which allows to subcompose the actual content during the measuring stage for example to use the values calculated during the measurement as params for the composition of the children.

static final void

Analogue of Layout which allows to subcompose the actual content during the measuring stage for example to use the values calculated during the measurement as params for the composition of the children.

static final void

Analogue of Layout which allows to subcompose the actual content during the measuring stage for example to use the values calculated during the measurement as params for the composition of the children.

static final @NonNull SubcomposeSlotReusePolicy
SubcomposeSlotReusePolicy(int maxSlotsToRetainForReuse)

Creates SubcomposeSlotReusePolicy which retains the fixed amount of slots.

Public methods

SubcomposeLayout

@Composable
public static final void SubcomposeLayout(
    @NonNull Modifier modifier,
    @ExtensionFunctionType @NonNull Function2<@NonNull SubcomposeMeasureScope, @NonNull Constraints, @NonNull MeasureResult> measurePolicy
)

Analogue of Layout which allows to subcompose the actual content during the measuring stage for example to use the values calculated during the measurement as params for the composition of the children.

Possible use cases:

import androidx.compose.ui.layout.SubcomposeLayout
import androidx.compose.ui.unit.IntSize

// enum class SlotsEnum { Main, Dependent }
SubcomposeLayout { constraints ->
    val mainPlaceables = subcompose(SlotsEnum.Main, mainContent).map {
        it.measure(constraints)
    }
    val maxSize = mainPlaceables.fold(IntSize.Zero) { currentMax, placeable ->
        IntSize(
            width = maxOf(currentMax.width, placeable.width),
            height = maxOf(currentMax.height, placeable.height)
        )
    }
    layout(maxSize.width, maxSize.height) {
        mainPlaceables.forEach { it.placeRelative(0, 0) }
        subcompose(SlotsEnum.Dependent) {
            dependentContent(maxSize)
        }.forEach {
            it.measure(constraints).placeRelative(0, 0)
        }
    }
}
Parameters
@NonNull Modifier modifier

Modifier to apply for the layout.

@ExtensionFunctionType @NonNull Function2<@NonNull SubcomposeMeasureScope, @NonNull Constraints, @NonNull MeasureResult> measurePolicy

Measure policy which provides ability to subcompose during the measuring.

SubcomposeLayout

@ExperimentalComposeUiApi
@Composable
public static final void SubcomposeLayout(
    @NonNull Modifier modifier,
    @ExtensionFunctionType @NonNull Function2<@NonNull SubcomposeIntermediateMeasureScope, @NonNull Constraints, @NonNull MeasureResult> intermediateMeasurePolicy,
    @ExtensionFunctionType @NonNull Function2<@NonNull SubcomposeMeasureScope, @NonNull Constraints, @NonNull MeasureResult> measurePolicy
)

Analogue of Layout which allows to subcompose the actual content during the measuring stage for example to use the values calculated during the measurement as params for the composition of the children.

When in a LookaheadScope, SubcomposeLayout will be measured up to twice per frame. The two measurements will be using different measure policies and potentially different constraints.

The first measurement happens in the lookahead pass, where new layout is calculated based on the target constraints. Therefore, measurePolicy will receive the target constraints, and subcompose its content based on the target constraints. Note: Target constraints refers to the constraints that the SubcomposeLayout will receive once all the lookahead-based animations on size/constraints in the ancestor layouts have finished.

The second measurement is done in the intermediate measure pass after the lookahead pass. The intermediate measure pass allows adjustments to the measurement/placement using the pre-calculated layout information as animation targets to smooth over any any layout changes. In this measurement, intermediateMeasurePolicy will be invoked with the intermediate/animating constraints. By default, measurePolicy will be invoked in intermediateMeasurePolicy, and hence the same measure logic in measurePolicy with intermediate constraints will be used to measure and layout children in the intermediate pass.

Note: When measurePolicy is invoked in the intermediate pass, subcompose will simply return the measurables associated with the given slot id based on the subcomposition during lookahead pass. This means if a given slot id has not been subcomposed in the lookahead pass, invoking subcompose during intermediate pass will result in an empty list.

Possible use cases:

import androidx.compose.runtime.Composable
import androidx.compose.ui.layout.SubcomposeLayout
import androidx.compose.ui.unit.IntSize

// In this example, there is a custom modifier that animates the constraints and measures
// child with the animated constraints, as defined below.
// This modifier is built on top of `Modifier.intermediateLayout`, which
// allows access to the lookahead size of the layout. A resize animation will be kicked off
// whenever the lookahead size changes, to animate children from current size to lookahead size.
// Fixed constraints created based on the animation value will be used to measure
// child, so the child layout gradually changes its size and potentially its child's placement
// to fit within the animated constraints.
fun Modifier.animateConstraints() = composed {
    // Creates a size animation
    var sizeAnimation: Animatable<IntSize, AnimationVector2D>? by remember {
        mutableStateOf(null)
    }

    this.intermediateLayout { measurable, _ ->
        // When layout changes, the lookahead pass will calculate a new final size for the
        // child layout. This lookahead size can be used to animate the size
        // change, such that the animation starts from the current size and gradually
        // change towards `lookaheadSize`.
        if (lookaheadSize != sizeAnimation?.targetValue) {
            sizeAnimation?.run {
                launch { animateTo(lookaheadSize) }
            } ?: Animatable(lookaheadSize, IntSize.VectorConverter).let {
                sizeAnimation = it
            }
        }
        val (width, height) = sizeAnimation!!.value
        // Creates a fixed set of constraints using the animated size
        val animatedConstraints = Constraints.fixed(width, height)
        // Measure child with animated constraints.
        val placeable = measurable.measure(animatedConstraints)
        layout(placeable.width, placeable.height) {
            placeable.place(0, 0)
        }
    }
}

// In the example below, the SubcomposeLayout has a parent layout that animates its width
// between two fixed sizes using the `animateConstraints` modifier we created above.
@Composable
fun SubcomposeLayoutWithAnimatingParentLayout(
    isWide: Boolean,
    modifier: Modifier = Modifier,
    content: @Composable @UiComposable () -> Unit
) {
    // Create a MeasurePolicy to measure all children with incoming constraints and return the
    // largest width & height.
    val myMeasurePolicy = MeasurePolicy { measurables, constraints ->
        val placeables = measurables.map { it.measure(constraints) }
        val maxWidth = placeables.maxOf { it.width }
        val maxHeight = placeables.maxOf { it.height }
        layout(maxWidth, maxHeight) {
            placeables.forEach { it.place(0, 0) }
        }
    }
    Box(
        Modifier
            .requiredSize(if (isWide) 400.dp else 200.dp)
            .animateConstraints()
    ) {
        // SubcomposeLayout's measurePolicy will only be invoked with lookahead constraints.
        // The parent layout in this example is animating between two fixed widths. The
        // [measurePolicy] parameter will only be called with lookahead constraints
        // (i.e. constraints for 400.dp x 400.dp or 200.dp x 200.dp depending on the state.)
        // This may cause content lambda to jump to its final size. To create a smooth
        // experience, we need to remeasure the content with the intermediate
        // constraints created by the `animateConstraints` that we built above. Therefore, we
        // need to provide a [intermediateMeasurePolicy] to define how to measure the
        // content (using the measureables of the content that was composed in [measurePolicy])
        // with intermediate constraints.
        SubcomposeLayout(
            modifier,
            intermediateMeasurePolicy = { intermediateConstraints ->
                // Retrieve the measureables for slotId = Unit, and measure them with
                // intermediate constraints using the measurePolicy we created above.
                with(myMeasurePolicy) {
                    measure(
                        measurablesForSlot(Unit),
                        intermediateConstraints
                    )
                }
            },
            measurePolicy = { constraints ->
                val measurables = subcompose(Unit) { content() }
                with(myMeasurePolicy) { measure(measurables, constraints) }
            })
    }
}
Parameters
@NonNull Modifier modifier

Modifier to apply for the layout.

@ExtensionFunctionType @NonNull Function2<@NonNull SubcomposeIntermediateMeasureScope, @NonNull Constraints, @NonNull MeasureResult> intermediateMeasurePolicy

A measure policy that will be invoked during the intermediate measure pass.

@ExtensionFunctionType @NonNull Function2<@NonNull SubcomposeMeasureScope, @NonNull Constraints, @NonNull MeasureResult> measurePolicy

Measure policy which provides ability to subcompose during the measuring.

SubcomposeLayout

@Composable
@UiComposable
public static final void SubcomposeLayout(
    @NonNull SubcomposeLayoutState state,
    @NonNull Modifier modifier,
    @ExtensionFunctionType @NonNull Function2<@NonNull SubcomposeMeasureScope, @NonNull Constraints, @NonNull MeasureResult> measurePolicy
)

Analogue of Layout which allows to subcompose the actual content during the measuring stage for example to use the values calculated during the measurement as params for the composition of the children.

Possible use cases:

import androidx.compose.ui.layout.SubcomposeLayout
import androidx.compose.ui.unit.IntSize

// enum class SlotsEnum { Main, Dependent }
SubcomposeLayout { constraints ->
    val mainPlaceables = subcompose(SlotsEnum.Main, mainContent).map {
        it.measure(constraints)
    }
    val maxSize = mainPlaceables.fold(IntSize.Zero) { currentMax, placeable ->
        IntSize(
            width = maxOf(currentMax.width, placeable.width),
            height = maxOf(currentMax.height, placeable.height)
        )
    }
    layout(maxSize.width, maxSize.height) {
        mainPlaceables.forEach { it.placeRelative(0, 0) }
        subcompose(SlotsEnum.Dependent) {
            dependentContent(maxSize)
        }.forEach {
            it.measure(constraints).placeRelative(0, 0)
        }
    }
}
Parameters
@NonNull SubcomposeLayoutState state

the state object to be used by the layout.

@NonNull Modifier modifier

Modifier to apply for the layout.

@ExtensionFunctionType @NonNull Function2<@NonNull SubcomposeMeasureScope, @NonNull Constraints, @NonNull MeasureResult> measurePolicy

Measure policy which provides ability to subcompose during the measuring.

SubcomposeLayout

@Composable
@UiComposable
@ExperimentalComposeUiApi
public static final void SubcomposeLayout(
    @NonNull SubcomposeLayoutState state,
    @NonNull Modifier modifier,
    @ExtensionFunctionType @NonNull Function2<@NonNull SubcomposeIntermediateMeasureScope, @NonNull Constraints, @NonNull MeasureResult> intermediateMeasurePolicy,
    @ExtensionFunctionType @NonNull Function2<@NonNull SubcomposeMeasureScope, @NonNull Constraints, @NonNull MeasureResult> measurePolicy
)

Analogue of Layout which allows to subcompose the actual content during the measuring stage for example to use the values calculated during the measurement as params for the composition of the children.

When in a LookaheadScope, SubcomposeLayout will be measured up to twice per frame. The two measurements will be using different measure policies and potentially different constraints.

The first measurement happens in the lookahead pass, where new layout is calculated based on the target constraints. Therefore, measurePolicy will receive the target constraints, and subcompose its content based on the target constraints. Note: Target constraints refers to the constraints that the SubcomposeLayout will receive once all the lookahead-based animations on size/constraints in the ancestor layouts have finished.

The second measurement is done in the intermediate measure pass after the lookahead pass. The intermediate measure pass allows adjustments to the measurement/placement using the pre-calculated layout information as animation targets to smooth over any any layout changes. In this measurement, intermediateMeasurePolicy will be invoked with the intermediate/animating constraints. By default, measurePolicy will be invoked in intermediateMeasurePolicy, and hence the same measure logic in measurePolicy with intermediate constraints will be used to measure and layout children in the intermediate pass.

Note: When measurePolicy is invoked in the intermediate pass, subcompose will simply return the measurables associated with the given slot id based on the subcomposition during lookahead pass. This means if a given slot id has not been subcomposed in the lookahead pass, invoking subcompose during intermediate pass will result in an empty list.

Possible use cases:

Parameters
@NonNull SubcomposeLayoutState state

the state object to be used by the layout.

@NonNull Modifier modifier

Modifier to apply for the layout.

@ExtensionFunctionType @NonNull Function2<@NonNull SubcomposeIntermediateMeasureScope, @NonNull Constraints, @NonNull MeasureResult> intermediateMeasurePolicy

A measure policy that will be invoked during the intermediate measure pass.

@ExtensionFunctionType @NonNull Function2<@NonNull SubcomposeMeasureScope, @NonNull Constraints, @NonNull MeasureResult> measurePolicy

Measure policy which provides ability to subcompose during the measuring.

SubcomposeSlotReusePolicy

public static final @NonNull SubcomposeSlotReusePolicy SubcomposeSlotReusePolicy(int maxSlotsToRetainForReuse)

Creates SubcomposeSlotReusePolicy which retains the fixed amount of slots.

Parameters
int maxSlotsToRetainForReuse

the SubcomposeLayout will retain up to this amount of slots.