LayoutModifierNode


Known direct subclasses
ApproachLayoutModifierNode

ApproachLayoutModifierNode is designed to support gradually approaching the destination layout calculated in the lookahead pass.


A Modifier.Node that changes how its wrapped content is measured and laid out. It has the same measurement and layout functionality as the androidx.compose.ui.layout.Layout component, while wrapping exactly one layout due to it being a modifier. In contrast, the androidx.compose.ui.layout.Layout component is used to define the layout behavior of multiple children.

This is the androidx.compose.ui.Modifier.Node equivalent of androidx.compose.ui.layout.LayoutModifier

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.layout.LayoutModifier
import androidx.compose.ui.layout.Measurable
import androidx.compose.ui.layout.MeasureResult
import androidx.compose.ui.layout.MeasureScope
import androidx.compose.ui.layout.layout
import androidx.compose.ui.node.LayoutModifierNode
import androidx.compose.ui.node.ModifierNodeElement
import androidx.compose.ui.platform.InspectorInfo
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.offset

class VerticalPadding(var padding: Dp) : LayoutModifierNode, Modifier.Node() {
    override fun MeasureScope.measure(
        measurable: Measurable,
        constraints: Constraints
    ): MeasureResult {
        val paddingPx = padding.roundToPx()
        val placeable = measurable.measure(constraints.offset(vertical = -paddingPx))
        return layout(placeable.width, placeable.height + paddingPx) {
            placeable.placeRelative(0, paddingPx)
        }
    }
}
data class VerticalPaddingElement(
    val padding: Dp
) : ModifierNodeElement<VerticalPadding>() {
    override fun create() = VerticalPadding(padding)
    override fun update(node: VerticalPadding) {
        node.padding = padding
    }
    override fun InspectorInfo.inspectableProperties() {
        name = "verticalPadding"
        properties["padding"] = padding
    }
}
fun Modifier.verticalPadding(padding: Dp) = this then VerticalPaddingElement(padding)
Box(Modifier.background(Color.Gray).verticalPadding(50.dp)) {
    Box(Modifier.fillMaxSize().background(Color.DarkGray))
}
See also
Layout

Summary

Public functions

open Int
IntrinsicMeasureScope.maxIntrinsicHeight(
    measurable: IntrinsicMeasurable,
    width: Int
)

The lambda used to calculate IntrinsicMeasurable.maxIntrinsicHeight.

Cmn
open Int
IntrinsicMeasureScope.maxIntrinsicWidth(
    measurable: IntrinsicMeasurable,
    height: Int
)

The function used to calculate IntrinsicMeasurable.maxIntrinsicWidth.

Cmn
MeasureResult
MeasureScope.measure(measurable: Measurable, constraints: Constraints)

The function used to measure the modifier.

Cmn
open Int
IntrinsicMeasureScope.minIntrinsicHeight(
    measurable: IntrinsicMeasurable,
    width: Int
)

The lambda used to calculate IntrinsicMeasurable.minIntrinsicHeight.

Cmn
open Int
IntrinsicMeasureScope.minIntrinsicWidth(
    measurable: IntrinsicMeasurable,
    height: Int
)

The function used to calculate IntrinsicMeasurable.minIntrinsicWidth.

Cmn

Extension functions

Unit

This will invalidate the current node's layer, and ensure that the layer is redrawn for the next frame.

Cmn
Unit

This invalidates the current node's measure result, and ensures that a re-measurement (the measurement block rerun) of this node will happen for the next frame.

Cmn
Unit

This will invalidate the current node's placement result, and ensure that relayout (the placement block rerun) of this node will happen for the next frame .

Cmn
Unit

Performs the node remeasuring synchronously even if the node was not marked as needs remeasure before.

Cmn

Inherited properties

From androidx.compose.ui.node.DelegatableNode
Modifier.Node

A reference of the Modifier.Node that holds this node's position in the node hierarchy.

Cmn

Public functions

maxIntrinsicHeight

open fun IntrinsicMeasureScope.maxIntrinsicHeight(
    measurable: IntrinsicMeasurable,
    width: Int
): Int

The lambda used to calculate IntrinsicMeasurable.maxIntrinsicHeight.

maxIntrinsicWidth

open fun IntrinsicMeasureScope.maxIntrinsicWidth(
    measurable: IntrinsicMeasurable,
    height: Int
): Int

The function used to calculate IntrinsicMeasurable.maxIntrinsicWidth.

measure

fun MeasureScope.measure(measurable: Measurable, constraints: Constraints): MeasureResult

The function used to measure the modifier. The measurable corresponds to the wrapped content, and it can be measured with the desired constraints according to the logic of the LayoutModifierNode. The modifier needs to choose its own size, which can depend on the size chosen by the wrapped content (the obtained Placeable), if the wrapped content was measured. The size needs to be returned as part of a MeasureResult, alongside the placement logic of the Placeable, which defines how the wrapped content should be positioned inside the LayoutModifierNode. A convenient way to create the MeasureResult is to use the MeasureScope.layout factory function.

A LayoutModifierNode uses the same measurement and layout concepts and principles as a androidx.compose.ui.layout.Layout, the only difference is that they apply to exactly one child. For a more detailed explanation of measurement and layout, see androidx.compose.ui.layout.MeasurePolicy.

minIntrinsicHeight

open fun IntrinsicMeasureScope.minIntrinsicHeight(
    measurable: IntrinsicMeasurable,
    width: Int
): Int

The lambda used to calculate IntrinsicMeasurable.minIntrinsicHeight.

minIntrinsicWidth

open fun IntrinsicMeasureScope.minIntrinsicWidth(
    measurable: IntrinsicMeasurable,
    height: Int
): Int

The function used to calculate IntrinsicMeasurable.minIntrinsicWidth.

Extension functions

invalidateLayer

fun LayoutModifierNode.invalidateLayer(): Unit

This will invalidate the current node's layer, and ensure that the layer is redrawn for the next frame.

invalidateMeasurement

fun LayoutModifierNode.invalidateMeasurement(): Unit

This invalidates the current node's measure result, and ensures that a re-measurement (the measurement block rerun) of this node will happen for the next frame.

invalidatePlacement

fun LayoutModifierNode.invalidatePlacement(): Unit

This will invalidate the current node's placement result, and ensure that relayout (the placement block rerun) of this node will happen for the next frame .

remeasureSync

fun LayoutModifierNode.remeasureSync(): Unit

Performs the node remeasuring synchronously even if the node was not marked as needs remeasure before. Useful for cases like when during scrolling you need to re-execute the measure block to consume the scroll offset and remeasure your children in a blocking way.