Layout

Functions summary

inline Unit
@Composable
@UiComposable
Layout(modifier: Modifier, measurePolicy: MeasurePolicy)

Layout is the main core component for layout for "leaf" nodes.

Cmn
inline Unit
@UiComposable
@Composable
Layout(
    content: @Composable @UiComposable () -> Unit,
    modifier: Modifier,
    measurePolicy: MeasurePolicy
)

Layout is the main core component for layout.

Cmn
inline Unit
@UiComposable
@Composable
Layout(
    contents: List<@Composable @UiComposable () -> Unit>,
    modifier: Modifier,
    measurePolicy: MultiContentMeasurePolicy
)

Layout is the main core component for layout.

Cmn

Functions

Layout

@Composable
@UiComposable
inline fun Layout(modifier: Modifier = Modifier, measurePolicy: MeasurePolicy): Unit

Layout is the main core component for layout for "leaf" nodes. It can be used to measure and position zero children.

The measurement, layout and intrinsic measurement behaviours of this layout will be defined by the measurePolicy instance. See MeasurePolicy for more details.

For a composable able to define its content according to the incoming constraints, see androidx.compose.foundation.layout.BoxWithConstraints.

Example usage:

import androidx.compose.ui.layout.Layout
import androidx.compose.ui.layout.layout
import androidx.compose.ui.unit.Constraints

// We build a layout that will occupy twice as much space as its children,
// and will position them to be bottom right aligned.
Layout(content) { measurables, constraints ->
    // measurables contains one element corresponding to each of our layout children.
    // constraints are the constraints that our parent is currently measuring us with.
    val childConstraints =
        Constraints(
            minWidth = constraints.minWidth / 2,
            minHeight = constraints.minHeight / 2,
            maxWidth =
                if (constraints.hasBoundedWidth) {
                    constraints.maxWidth / 2
                } else {
                    Constraints.Infinity
                },
            maxHeight =
                if (constraints.hasBoundedHeight) {
                    constraints.maxHeight / 2
                } else {
                    Constraints.Infinity
                },
        )
    // We measure the children with half our constraints, to ensure we can be double
    // the size of the children.
    val placeables = measurables.map { it.measure(childConstraints) }
    val layoutWidth = (placeables.maxByOrNull { it.width }?.width ?: 0) * 2
    val layoutHeight = (placeables.maxByOrNull { it.height }?.height ?: 0) * 2
    // We call layout to set the size of the current layout and to provide the positioning
    // of the children. The children are placed relative to the current layout place.
    layout(layoutWidth, layoutHeight) {
        placeables.forEach {
            it.placeRelative(layoutWidth - it.width, layoutHeight - it.height)
        }
    }
}

Example usage with custom intrinsic measurements:

import androidx.compose.ui.layout.IntrinsicMeasurable
import androidx.compose.ui.layout.IntrinsicMeasureScope
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.layout.Measurable
import androidx.compose.ui.layout.MeasurePolicy
import androidx.compose.ui.layout.MeasureResult
import androidx.compose.ui.layout.MeasureScope
import androidx.compose.ui.layout.layout
import androidx.compose.ui.unit.Constraints

// We build a layout that will occupy twice as much space as its children,
// and will position them to be bottom right aligned.
val measurePolicy =
    object : MeasurePolicy {
        override fun MeasureScope.measure(
            measurables: List<Measurable>,
            constraints: Constraints,
        ): MeasureResult {
            // measurables contains one element corresponding to each of our layout children.
            // constraints are the constraints that our parent is currently measuring us with.
            val childConstraints =
                Constraints(
                    minWidth = constraints.minWidth / 2,
                    minHeight = constraints.minHeight / 2,
                    maxWidth =
                        if (constraints.hasBoundedWidth) {
                            constraints.maxWidth / 2
                        } else {
                            Constraints.Infinity
                        },
                    maxHeight =
                        if (constraints.hasBoundedHeight) {
                            constraints.maxHeight / 2
                        } else {
                            Constraints.Infinity
                        },
                )
            // We measure the children with half our constraints, to ensure we can be double
            // the size of the children.
            val placeables = measurables.map { it.measure(childConstraints) }
            val layoutWidth = (placeables.maxByOrNull { it.width }?.width ?: 0) * 2
            val layoutHeight = (placeables.maxByOrNull { it.height }?.height ?: 0) * 2
            // We call layout to set the size of the current layout and to provide the
            // positioning
            // of the children. The children are placed relative to the current layout place.
            return layout(layoutWidth, layoutHeight) {
                placeables.forEach {
                    it.placeRelative(layoutWidth - it.width, layoutHeight - it.height)
                }
            }
        }

        // The min intrinsic width of this layout will be twice the largest min intrinsic
        // width of a child. Note that we call minIntrinsicWidth with h / 2 for children,
        // since we should be double the size of the children.
        override fun IntrinsicMeasureScope.minIntrinsicWidth(
            measurables: List<IntrinsicMeasurable>,
            height: Int,
        ) = (measurables.map { it.minIntrinsicWidth(height / 2) }.maxByOrNull { it } ?: 0) * 2

        override fun IntrinsicMeasureScope.minIntrinsicHeight(
            measurables: List<IntrinsicMeasurable>,
            width: Int,
        ) = (measurables.map { it.minIntrinsicHeight(width / 2) }.maxByOrNull { it } ?: 0) * 2

        override fun IntrinsicMeasureScope.maxIntrinsicWidth(
            measurables: List<IntrinsicMeasurable>,
            height: Int,
        ) = (measurables.map { it.maxIntrinsicWidth(height / 2) }.maxByOrNull { it } ?: 0) * 2

        override fun IntrinsicMeasureScope.maxIntrinsicHeight(
            measurables: List<IntrinsicMeasurable>,
            width: Int,
        ) = (measurables.map { it.maxIntrinsicHeight(width / 2) }.maxByOrNull { it } ?: 0) * 2
    }

Layout(content = content, measurePolicy = measurePolicy)
Parameters
modifier: Modifier = Modifier

Modifiers to be applied to the layout.

measurePolicy: MeasurePolicy

The policy defining the measurement and positioning of the layout.

Layout

@UiComposable
@Composable
inline fun Layout(
    content: @Composable @UiComposable () -> Unit,
    modifier: Modifier = Modifier,
    measurePolicy: MeasurePolicy
): Unit

Layout is the main core component for layout. It can be used to measure and position zero or more layout children.

The measurement, layout and intrinsic measurement behaviours of this layout will be defined by the measurePolicy instance. See MeasurePolicy for more details.

For a composable able to define its content according to the incoming constraints, see androidx.compose.foundation.layout.BoxWithConstraints.

Example usage:

import androidx.compose.ui.layout.Layout
import androidx.compose.ui.layout.layout
import androidx.compose.ui.unit.Constraints

// We build a layout that will occupy twice as much space as its children,
// and will position them to be bottom right aligned.
Layout(content) { measurables, constraints ->
    // measurables contains one element corresponding to each of our layout children.
    // constraints are the constraints that our parent is currently measuring us with.
    val childConstraints =
        Constraints(
            minWidth = constraints.minWidth / 2,
            minHeight = constraints.minHeight / 2,
            maxWidth =
                if (constraints.hasBoundedWidth) {
                    constraints.maxWidth / 2
                } else {
                    Constraints.Infinity
                },
            maxHeight =
                if (constraints.hasBoundedHeight) {
                    constraints.maxHeight / 2
                } else {
                    Constraints.Infinity
                },
        )
    // We measure the children with half our constraints, to ensure we can be double
    // the size of the children.
    val placeables = measurables.map { it.measure(childConstraints) }
    val layoutWidth = (placeables.maxByOrNull { it.width }?.width ?: 0) * 2
    val layoutHeight = (placeables.maxByOrNull { it.height }?.height ?: 0) * 2
    // We call layout to set the size of the current layout and to provide the positioning
    // of the children. The children are placed relative to the current layout place.
    layout(layoutWidth, layoutHeight) {
        placeables.forEach {
            it.placeRelative(layoutWidth - it.width, layoutHeight - it.height)
        }
    }
}

Example usage with custom intrinsic measurements:

import androidx.compose.ui.layout.IntrinsicMeasurable
import androidx.compose.ui.layout.IntrinsicMeasureScope
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.layout.Measurable
import androidx.compose.ui.layout.MeasurePolicy
import androidx.compose.ui.layout.MeasureResult
import androidx.compose.ui.layout.MeasureScope
import androidx.compose.ui.layout.layout
import androidx.compose.ui.unit.Constraints

// We build a layout that will occupy twice as much space as its children,
// and will position them to be bottom right aligned.
val measurePolicy =
    object : MeasurePolicy {
        override fun MeasureScope.measure(
            measurables: List<Measurable>,
            constraints: Constraints,
        ): MeasureResult {
            // measurables contains one element corresponding to each of our layout children.
            // constraints are the constraints that our parent is currently measuring us with.
            val childConstraints =
                Constraints(
                    minWidth = constraints.minWidth / 2,
                    minHeight = constraints.minHeight / 2,
                    maxWidth =
                        if (constraints.hasBoundedWidth) {
                            constraints.maxWidth / 2
                        } else {
                            Constraints.Infinity
                        },
                    maxHeight =
                        if (constraints.hasBoundedHeight) {
                            constraints.maxHeight / 2
                        } else {
                            Constraints.Infinity
                        },
                )
            // We measure the children with half our constraints, to ensure we can be double
            // the size of the children.
            val placeables = measurables.map { it.measure(childConstraints) }
            val layoutWidth = (placeables.maxByOrNull { it.width }?.width ?: 0) * 2
            val layoutHeight = (placeables.maxByOrNull { it.height }?.height ?: 0) * 2
            // We call layout to set the size of the current layout and to provide the
            // positioning
            // of the children. The children are placed relative to the current layout place.
            return layout(layoutWidth, layoutHeight) {
                placeables.forEach {
                    it.placeRelative(layoutWidth - it.width, layoutHeight - it.height)
                }
            }
        }

        // The min intrinsic width of this layout will be twice the largest min intrinsic
        // width of a child. Note that we call minIntrinsicWidth with h / 2 for children,
        // since we should be double the size of the children.
        override fun IntrinsicMeasureScope.minIntrinsicWidth(
            measurables: List<IntrinsicMeasurable>,
            height: Int,
        ) = (measurables.map { it.minIntrinsicWidth(height / 2) }.maxByOrNull { it } ?: 0) * 2

        override fun IntrinsicMeasureScope.minIntrinsicHeight(
            measurables: List<IntrinsicMeasurable>,
            width: Int,
        ) = (measurables.map { it.minIntrinsicHeight(width / 2) }.maxByOrNull { it } ?: 0) * 2

        override fun IntrinsicMeasureScope.maxIntrinsicWidth(
            measurables: List<IntrinsicMeasurable>,
            height: Int,
        ) = (measurables.map { it.maxIntrinsicWidth(height / 2) }.maxByOrNull { it } ?: 0) * 2

        override fun IntrinsicMeasureScope.maxIntrinsicHeight(
            measurables: List<IntrinsicMeasurable>,
            width: Int,
        ) = (measurables.map { it.maxIntrinsicHeight(width / 2) }.maxByOrNull { it } ?: 0) * 2
    }

Layout(content = content, measurePolicy = measurePolicy)
Parameters
content: @Composable @UiComposable () -> Unit

The children composable to be laid out.

modifier: Modifier = Modifier

Modifiers to be applied to the layout.

measurePolicy: MeasurePolicy

The policy defining the measurement and positioning of the layout.

Layout

@UiComposable
@Composable
inline fun Layout(
    contents: List<@Composable @UiComposable () -> Unit>,
    modifier: Modifier = Modifier,
    measurePolicy: MultiContentMeasurePolicy
): Unit

Layout is the main core component for layout. It can be used to measure and position zero or more layout children.

This overload accepts a list of multiple composable content lambdas, which allows treating measurables put into different content lambdas differently - measure policy will provide a list of lists of Measurables, not just a single list. Such list has the same size as the list of contents passed into Layout and contains the list of measurables of the corresponding content lambda in the same order.

Note that layouts emitted as part of all contents lambdas will be added as a direct children for this Layout. This means that if you set a custom z index on some children, the drawing order will be calculated as if they were all provided as part of one lambda.

Example usage:

import androidx.compose.ui.layout.Layout
import androidx.compose.ui.layout.Measurable
import androidx.compose.ui.layout.layout

// We can provide pass a list of two composable lambdas in order to be able to treat
// measureables from each lambda differently.
Layout(listOf(content1, content2)) { (content1Measurables, content2Measurables), constraints ->
    val content1Placeables = content1Measurables.map { it.measure(constraints) }
    val content2Placeables = content2Measurables.map { it.measure(constraints) }
    layout(constraints.maxWidth, constraints.maxHeight) {
        var currentX = 0
        var currentY = 0
        var currentMaxHeight = 0
        // we place placeables from content1 as a first line
        content1Placeables.forEach {
            it.place(currentX, currentY)
            currentX += it.width
            currentMaxHeight = maxOf(currentMaxHeight, it.height)
        }
        currentX = 0
        currentY = currentMaxHeight
        // and placeables from content2 composable as a second line
        content2Placeables.forEach {
            it.place(currentX, currentY)
            currentX += it.width
        }
    }
}
Parameters
contents: List<@Composable @UiComposable () -> Unit>

The list of children composable contents to be laid out.

modifier: Modifier = Modifier

Modifiers to be applied to the layout.

measurePolicy: MultiContentMeasurePolicy

The policy defining the measurement and positioning of the layout.

See also
Layout

for a simpler use case when you have only one content lambda.