# LayoutAwareModifierNode

Artifact: [androidx.compose.ui:ui](https://developer.android.com/jetpack/androidx/releases/compose-ui) [View Source](https://cs.android.com/search?q=file:androidx/compose/ui/node/LayoutAwareModifierNode.kt+class:androidx.compose.ui.node.LayoutAwareModifierNode) Added in [1.3.0](https://developer.android.com/jetpack/androidx/releases/compose-ui#1.3.0) Common/AllAndroid/JVM
- Cmn

  ```
  interface LayoutAwareModifierNode : MeasuredSizeAwareModifierNode, DelegatableNode
  ```
Known direct subclasses [DragAndDropSourceModifierNode](https://developer.android.com/reference/kotlin/androidx/compose/ui/draganddrop/DragAndDropSourceModifierNode), [DragAndDropTargetModifierNode](https://developer.android.com/reference/kotlin/androidx/compose/ui/draganddrop/DragAndDropTargetModifierNode)

|---|---|
| `https://developer.android.com/reference/kotlin/androidx/compose/ui/draganddrop/DragAndDropSourceModifierNode` | A `https://developer.android.com/reference/kotlin/androidx/compose/ui/Modifier.Node` that can be used as a source for platform drag and drop operations. |
| `https://developer.android.com/reference/kotlin/androidx/compose/ui/draganddrop/DragAndDropTargetModifierNode` | A `https://developer.android.com/reference/kotlin/androidx/compose/ui/Modifier.Node` that can be used as a target for platform drag and drop operations. |

*** ** * ** ***

A `https://developer.android.com/reference/kotlin/androidx/compose/ui/Modifier.Node` which receives various callbacks in response to local changes in layout.

This is the `https://developer.android.com/reference/kotlin/androidx/compose/ui/Modifier.Node` equivalent of `https://developer.android.com/reference/kotlin/androidx/compose/ui/layout/OnRemeasuredModifier` and `https://developer.android.com/reference/kotlin/androidx/compose/ui/layout/OnPlacedModifier`

Example usage:

```kotlin
import androidx.compose.material3.Text
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.onSizeChanged

// Use onSizeChanged() for diagnostics. Use Layout or SubcomposeLayout if you want
// to use the size of one component to affect the size of another component.
Text(
    "Hello $name",
    Modifier.onSizeChanged { size -> println("The size of the Text in pixels is $size") },
)
```

```kotlin
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.AnimationVector2D
import androidx.compose.animation.core.Spring.StiffnessMediumLow
import androidx.compose.animation.core.VectorConverter
import androidx.compose.animation.core.spring
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.onPlaced
import androidx.compose.ui.layout.positionInParent
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.round

fun Modifier.animatePlacement(): Modifier = composed {
    val scope = rememberCoroutineScope()
    var targetOffset by remember { mutableStateOf(IntOffset.Zero) }
    var animatable by remember {
        mutableStateOf<Animatable<IntOffset, AnimationVector2D>?>(null)
    }
    this.onPlaced {
            // Calculate the position in the parent layout
            targetOffset = it.positionInParent().round()
        }
        .offset {
            // Animate to the new target offset when alignment changes.
            val anim =
                animatable
                    ?: Animatable(targetOffset, IntOffset.VectorConverter).also {
                        animatable = it
                    }
            if (anim.targetValue != targetOffset) {
                scope.launch {
                    anim.animateTo(targetOffset, spring(stiffness = StiffnessMediumLow))
                }
            }
            // Offset the child in the opposite direction to the targetOffset, and slowly catch
            // up to zero offset via an animation to achieve an overall animated movement.
            animatable?.let { it.value - targetOffset } ?: IntOffset.Zero
        }
}

@Composable
fun AnimatedChildAlignment(alignment: Alignment) {
    Box(Modifier.fillMaxSize().padding(4.dp).border(1.dp, Color.Red)) {
        Box(
            modifier =
                Modifier.animatePlacement().align(alignment).size(100.dp).background(Color.Red)
        )
    }
}
```

```kotlin
import androidx.compose.ui.Modifier
import androidx.compose.ui.node.LayoutAwareModifierNode
import androidx.compose.ui.node.ModifierNodeElement
import androidx.compose.ui.platform.InspectorInfo
import androidx.compose.ui.unit.IntSize

class SizeLoggerNode(var id: String) : LayoutAwareModifierNode, Modifier.Node() {
    override fun onRemeasured(size: IntSize) {
        println("The size of $id was $size")
    }
}

data class LogSizeElement(val id: String) : ModifierNodeElement<SizeLoggerNode>() {
    override fun create(): SizeLoggerNode = SizeLoggerNode(id)

    override fun update(node: SizeLoggerNode) {
        node.id = id
    }

    override fun InspectorInfo.inspectableProperties() {
        name = "logSize"
        properties["id"] = id
    }
}

fun Modifier.logSize(id: String) = this then LogSizeElement(id)
```

## Summary

| ### Public functions |
|---|---|---|
| `open https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `@https://developer.android.com/reference/kotlin/androidx/annotation/EmptySuper https://developer.android.com/reference/kotlin/androidx/compose/ui/node/LayoutAwareModifierNode#onPlaced(androidx.compose.ui.layout.LayoutCoordinates)(coordinates: https://developer.android.com/reference/kotlin/androidx/compose/ui/layout/LayoutCoordinates)` `https://developer.android.com/reference/kotlin/androidx/compose/ui/node/LayoutAwareModifierNode#onPlaced(androidx.compose.ui.layout.LayoutCoordinates)` is called after the parent `https://developer.android.com/reference/kotlin/androidx/compose/ui/layout/LayoutModifier` and parent layout has been placed and before child `https://developer.android.com/reference/kotlin/androidx/compose/ui/layout/LayoutModifier` is placed. | Cmn |
| `open https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `@https://developer.android.com/reference/kotlin/androidx/annotation/EmptySuper https://developer.android.com/reference/kotlin/androidx/compose/ui/node/LayoutAwareModifierNode#onRemeasured(androidx.compose.ui.unit.IntSize)(size: https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/IntSize)` This method is called when the layout content is remeasured. | Cmn |

### Inherited functions

From [androidx.compose.ui.node.DelegatableNode](https://developer.android.com/reference/kotlin/androidx/compose/ui/node/DelegatableNode) `open https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` `@https://developer.android.com/reference/kotlin/androidx/annotation/EmptySuper
https://developer.android.com/reference/kotlin/androidx/compose/ui/node/DelegatableNode#onDensityChange()()`

Invoked when the density changes for this node.
Cmn `open https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` `@https://developer.android.com/reference/kotlin/androidx/annotation/EmptySuper
https://developer.android.com/reference/kotlin/androidx/compose/ui/node/DelegatableNode#onLayoutDirectionChange()()`

Invoked when the layout direction changes for this node.
Cmn

### Inherited properties

From [androidx.compose.ui.node.DelegatableNode](https://developer.android.com/reference/kotlin/androidx/compose/ui/node/DelegatableNode) `https://developer.android.com/reference/kotlin/androidx/compose/ui/Modifier.Node` `https://developer.android.com/reference/kotlin/androidx/compose/ui/node/DelegatableNode#node()`

A reference of the `https://developer.android.com/reference/kotlin/androidx/compose/ui/Modifier.Node` that holds this node's position in the node hierarchy.
Cmn

## Public functions

### onPlaced

Cmn Added in [1.3.0](https://developer.android.com/jetpack/androidx/releases/compose-ui#1.3.0)

```
@EmptySuper
open fun onPlaced(coordinates: LayoutCoordinates): Unit
```

`https://developer.android.com/reference/kotlin/androidx/compose/ui/node/LayoutAwareModifierNode#onPlaced(androidx.compose.ui.layout.LayoutCoordinates)` is called after the parent `https://developer.android.com/reference/kotlin/androidx/compose/ui/layout/LayoutModifier` and parent layout has been placed and before child `https://developer.android.com/reference/kotlin/androidx/compose/ui/layout/LayoutModifier` is placed. This allows child `https://developer.android.com/reference/kotlin/androidx/compose/ui/layout/LayoutModifier` to adjust its own placement based on where the parent is.

If you only need to access the current `https://developer.android.com/reference/kotlin/androidx/compose/ui/layout/LayoutCoordinates` at a single point in time from outside this method, use `https://developer.android.com/reference/kotlin/androidx/compose/ui/node/package-summary#(androidx.compose.ui.node.DelegatableNode).requireLayoutCoordinates()`.

| See also |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/compose/ui/node/UnplacedAwareModifierNode` | if you need to also be notified when the node is not placed anymore. |

### onRemeasured

Cmn Added in [1.10.0](https://developer.android.com/jetpack/androidx/releases/compose-ui#1.10.0)

```
@EmptySuper
open fun onRemeasured(size: IntSize): Unit
```

This method is called when the layout content is remeasured. The most common usage is `https://developer.android.com/reference/kotlin/androidx/compose/ui/layout/onSizeChanged.modifier#(androidx.compose.ui.Modifier).onSizeChanged(kotlin.Function1)`.