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

Placeable.PlacementScope

public abstract class Placeable.PlacementScope


Receiver scope that permits explicit placement of a Placeable.

While a Placeable may be placed at any time, this explicit receiver scope is used to discourage placement outside of MeasureScope.layout positioning blocks. This permits Compose UI to perform additional layout optimizations allowing repositioning a Placeable without remeasuring its original Measurable if factors contributing to its potential measurement have not changed. The scope also allows automatic mirroring of children positions in RTL layout direction contexts using the placeRelative methods available in the scope. If the automatic mirroring is not desired, place should be used instead.

Summary

Public constructors

Public methods

LayoutCoordinates

The LayoutCoordinates of this layout, if known or null if the layout hasn't been placed yet.

final void
place(
    @NonNull Placeable receiver,
    @NonNull IntOffset position,
    float zIndex
)

Place a Placeable at position in its parent's coordinate system.

final void
place(@NonNull Placeable receiver, int x, int y, float zIndex)

Place a Placeable at x, y in its parent's coordinate system.

final void
placeRelative(
    @NonNull Placeable receiver,
    @NonNull IntOffset position,
    float zIndex
)

Place a Placeable at position in its parent's coordinate system.

final void
placeRelative(@NonNull Placeable receiver, int x, int y, float zIndex)

Place a Placeable at x, y in its parent's coordinate system.

final void
placeRelativeWithLayer(
    @NonNull Placeable receiver,
    @NonNull IntOffset position,
    float zIndex,
    @ExtensionFunctionType @NonNull Function1<@NonNull GraphicsLayerScopeUnit> layerBlock
)

Place a Placeable at position in its parent's coordinate system with an introduced graphic layer.

final void
placeRelativeWithLayer(
    @NonNull Placeable receiver,
    int x,
    int y,
    float zIndex,
    @ExtensionFunctionType @NonNull Function1<@NonNull GraphicsLayerScopeUnit> layerBlock
)

Place a Placeable at x, y in its parent's coordinate system with an introduced graphic layer.

final void
placeWithLayer(
    @NonNull Placeable receiver,
    @NonNull IntOffset position,
    float zIndex,
    @ExtensionFunctionType @NonNull Function1<@NonNull GraphicsLayerScopeUnit> layerBlock
)

Place a Placeable at position in its parent's coordinate system with an introduced graphic layer.

final void
placeWithLayer(
    @NonNull Placeable receiver,
    int x,
    int y,
    float zIndex,
    @ExtensionFunctionType @NonNull Function1<@NonNull GraphicsLayerScopeUnit> layerBlock
)

Place a Placeable at x, y in its parent's coordinate system with an introduced graphic layer.

Protected methods

abstract @NonNull LayoutDirection

Keeps the layout direction of the parent of the placeable that is being places using current PlacementScope.

abstract int

Keeps the parent layout node's width to make the automatic mirroring of the position in RTL environment.

Public constructors

PlacementScope

public PlacementScope()

Public methods

getCoordinates

public LayoutCoordinates getCoordinates()

The LayoutCoordinates of this layout, if known or null if the layout hasn't been placed yet. coordinates will be null when determining alignment lines, preventing alignment lines from depending on absolute coordinates.

When coordinates is null, there will always be a follow-up placement call in which coordinates is not-null.

If you read a position from the coordinates during the placement block the block will be automatically re-executed when the parent layout changes a position. If you don't read it the placement block execution can be skipped as an optimization.

import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.layout.Placeable
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.round

// Layout so that the first item consumes to half of the width of the screen, if possible.
// The remainder of the layouts are positioned horizontally in the remaining space.
@Composable
fun FirstItemHalf(modifier: Modifier = Modifier, content: @Composable () -> Unit) {
    val view = LocalView.current

    Layout(content = content, modifier = modifier, measurePolicy = { measurables, constraints ->
        var width = constraints.minWidth
        var height = constraints.minHeight
        // If this doesn't have a fixed size, just layout horizontally
        var placeables: List<Placeable>? = null
        if (measurables.isNotEmpty()) {
            if (constraints.hasBoundedWidth && constraints.hasBoundedHeight) {
                width = constraints.maxWidth
                height = constraints.maxHeight
            } else {
                placeables = measurables.map { it.measure(constraints) }
                width = placeables.sumOf { it.width }
                height = placeables.maxOf { it.height }
            }
        }
        layout(width, height) {
            if (placeables != null) {
                var x = 0
                placeables.forEach {
                    it.placeRelative(x, 0)
                    x += it.width
                }
            } else if (measurables.isNotEmpty() && coordinates != null) {
                val coordinates = coordinates!!
                val positionInWindow = IntArray(2)
                view.getLocationOnScreen(positionInWindow)
                val topLeft = coordinates.localToRoot(Offset.Zero).round() +
                    IntOffset(positionInWindow[0], positionInWindow[1])
                val displayWidth = view.resources.displayMetrics.widthPixels
                val halfWay = displayWidth / 2

                val c0 = if (topLeft.x < halfWay) {
                    // The first measurable should fit to half way across
                    Constraints.fixed(
                        halfWay - topLeft.x,
                        height
                    )
                } else {
                    // The first is already past the half way, so just divide it evenly
                    val measureWidth = width / measurables.size
                    Constraints.fixed(measureWidth, height)
                }
                val p0 = measurables[0].measure(c0)
                p0.place(0, 0)

                // The rest just fit in the remainder of the space
                var x = p0.width
                for (i in 1..measurables.lastIndex) {
                    val measureWidth = (width - x) / (measurables.size - i)
                    val p = measurables[i].measure(Constraints.fixed(measureWidth, height))
                    p.place(x, 0)
                    x += p.width
                }
            }
        }
    })
}

place

public final void place(
    @NonNull Placeable receiver,
    @NonNull IntOffset position,
    float zIndex
)

Place a Placeable at position in its parent's coordinate system. Unlike placeRelative, the given position will not implicitly react in RTL layout direction contexts.

Parameters
float zIndex

controls the drawing order for the Placeable. A Placeable with larger zIndex will be drawn on top of all the children with smaller zIndex. When children have the same zIndex the order in which the items were placed is used.

place

public final void place(@NonNull Placeable receiver, int x, int y, float zIndex)

Place a Placeable at x, y in its parent's coordinate system. Unlike placeRelative, the given position will not implicitly react in RTL layout direction contexts.

Parameters
float zIndex

controls the drawing order for the Placeable. A Placeable with larger zIndex will be drawn on top of all the children with smaller zIndex. When children have the same zIndex the order in which the items were placed is used.

placeRelative

public final void placeRelative(
    @NonNull Placeable receiver,
    @NonNull IntOffset position,
    float zIndex
)

Place a Placeable at position in its parent's coordinate system. If the layout direction is right-to-left, the given position will be horizontally mirrored so that the position of the Placeable implicitly reacts to RTL layout direction contexts. If this method is used outside the MeasureScope.layout positioning block, the automatic position mirroring will not happen and the Placeable will be placed at the given position, similar to the place method.

Parameters
float zIndex

controls the drawing order for the Placeable. A Placeable with larger zIndex will be drawn on top of all the children with smaller zIndex. When children have the same zIndex the order in which the items were placed is used.

placeRelative

public final void placeRelative(@NonNull Placeable receiver, int x, int y, float zIndex)

Place a Placeable at x, y in its parent's coordinate system. If the layout direction is right-to-left, the given position will be horizontally mirrored so that the position of the Placeable implicitly reacts to RTL layout direction contexts. If this method is used outside the MeasureScope.layout positioning block, the automatic position mirroring will not happen and the Placeable will be placed at the given position, similar to the place method.

Parameters
float zIndex

controls the drawing order for the Placeable. A Placeable with larger zIndex will be drawn on top of all the children with smaller zIndex. When children have the same zIndex the order in which the items were placed is used.

placeRelativeWithLayer

public final void placeRelativeWithLayer(
    @NonNull Placeable receiver,
    @NonNull IntOffset position,
    float zIndex,
    @ExtensionFunctionType @NonNull Function1<@NonNull GraphicsLayerScopeUnit> layerBlock
)

Place a Placeable at position in its parent's coordinate system with an introduced graphic layer. If the layout direction is right-to-left, the given position will be horizontally mirrored so that the position of the Placeable implicitly reacts to RTL layout direction contexts. If this method is used outside the MeasureScope.layout positioning block, the automatic position mirroring will not happen and the Placeable will be placed at the given position, similar to the place method.

Parameters
float zIndex

controls the drawing order for the Placeable. A Placeable with larger zIndex will be drawn on top of all the children with smaller zIndex. When children have the same zIndex the order in which the items were placed is used.

@ExtensionFunctionType @NonNull Function1<@NonNull GraphicsLayerScopeUnit> layerBlock

You can configure any layer property available on GraphicsLayerScope via this block. If the Placeable will be placed with a new position next time only the graphic layer will be moved without requiring to redrawn the Placeable content.

placeRelativeWithLayer

public final void placeRelativeWithLayer(
    @NonNull Placeable receiver,
    int x,
    int y,
    float zIndex,
    @ExtensionFunctionType @NonNull Function1<@NonNull GraphicsLayerScopeUnit> layerBlock
)

Place a Placeable at x, y in its parent's coordinate system with an introduced graphic layer. If the layout direction is right-to-left, the given position will be horizontally mirrored so that the position of the Placeable implicitly reacts to RTL layout direction contexts. If this method is used outside the MeasureScope.layout positioning block, the automatic position mirroring will not happen and the Placeable will be placed at the given position, similar to the place method.

Parameters
float zIndex

controls the drawing order for the Placeable. A Placeable with larger zIndex will be drawn on top of all the children with smaller zIndex. When children have the same zIndex the order in which the items were placed is used.

@ExtensionFunctionType @NonNull Function1<@NonNull GraphicsLayerScopeUnit> layerBlock

You can configure any layer property available on GraphicsLayerScope via this block. If the Placeable will be placed with a new x or y next time only the graphic layer will be moved without requiring to redrawn the Placeable content.

placeWithLayer

public final void placeWithLayer(
    @NonNull Placeable receiver,
    @NonNull IntOffset position,
    float zIndex,
    @ExtensionFunctionType @NonNull Function1<@NonNull GraphicsLayerScopeUnit> layerBlock
)

Place a Placeable at position in its parent's coordinate system with an introduced graphic layer. Unlike placeRelative, the given position will not implicitly react in RTL layout direction contexts.

Parameters
float zIndex

controls the drawing order for the Placeable. A Placeable with larger zIndex will be drawn on top of all the children with smaller zIndex. When children have the same zIndex the order in which the items were placed is used.

@ExtensionFunctionType @NonNull Function1<@NonNull GraphicsLayerScopeUnit> layerBlock

You can configure any layer property available on GraphicsLayerScope via this block. If the Placeable will be placed with a new position next time only the graphic layer will be moved without requiring to redrawn the Placeable content.

placeWithLayer

public final void placeWithLayer(
    @NonNull Placeable receiver,
    int x,
    int y,
    float zIndex,
    @ExtensionFunctionType @NonNull Function1<@NonNull GraphicsLayerScopeUnit> layerBlock
)

Place a Placeable at x, y in its parent's coordinate system with an introduced graphic layer. Unlike placeRelative, the given position will not implicitly react in RTL layout direction contexts.

Parameters
float zIndex

controls the drawing order for the Placeable. A Placeable with larger zIndex will be drawn on top of all the children with smaller zIndex. When children have the same zIndex the order in which the items were placed is used.

@ExtensionFunctionType @NonNull Function1<@NonNull GraphicsLayerScopeUnit> layerBlock

You can configure any layer property available on GraphicsLayerScope via this block. If the Placeable will be placed with a new x or y next time only the graphic layer will be moved without requiring to redrawn the Placeable content.

Protected methods

getParentLayoutDirection

protected abstract @NonNull LayoutDirection getParentLayoutDirection()

Keeps the layout direction of the parent of the placeable that is being places using current PlacementScope. Used to support automatic position mirroring for convenient RTL support in custom layouts.

getParentWidth

protected abstract int getParentWidth()

Keeps the parent layout node's width to make the automatic mirroring of the position in RTL environment. If the value is zero, than the Placeable will be be placed to the original position (position will not be mirrored).