This Compose book is reviewed by Googlers Check it out →

recalculateWindowInsets

Common

Modifier in Compose Foundation Layout

This recalculates the [WindowInsets] based on the size and position. This only works when [Constraints] have [fixed width][Constraints.hasFixedWidth] and [fixed height][Constraints.hasFixedHeight]. This can be accomplished, for example, by having [Modifier.size], or [Modifier.fillMaxSize], or other size modifier before [recalculateWindowInsets]. If the [Constraints] sizes aren't fixed, [recalculateWindowInsets] won't adjust the [WindowInsets] and won't have any affect on layout.

[recalculateWindowInsets] is useful when the parent does not call [consumeWindowInsets] when it aligns a child. For example, a [Column] with two children should have different [WindowInsets] for each child. The top item should exclude insets below its bottom and the bottom item should exclude the top insets, but the Column can't assign different insets for different children.

Last updated:

Installation

dependencies {
   implementation("androidx.compose.foundation:foundation-layout:1.8.0-alpha04")
}

Overloads


fun Modifier.recalculateWindowInsets(): Modifier

Code Examples

recalculateWindowInsetsSample

@Composable
fun recalculateWindowInsetsSample() {
    var hasFirstItem by remember { mutableStateOf(true) }
    var hasLastItem by remember { mutableStateOf(true) }
    Column(Modifier.fillMaxSize()) {
        if (hasFirstItem) {
            Box(Modifier.weight(1f).fillMaxWidth().background(Color.Magenta))
        }
        Box(
            Modifier.fillMaxWidth() // force a fixed size on the content
                .recalculateWindowInsets()
                .weight(1f)
                .background(Color.Yellow)
                .safeDrawingPadding()
        ) {
            Button(
                onClick = { hasFirstItem = !hasFirstItem },
                Modifier.align(Alignment.TopCenter)
            ) {
                val action = if (hasFirstItem) "Remove" else "Add"
                Text("$action First Item")
            }
            Button(
                onClick = { hasLastItem = !hasLastItem },
                Modifier.align(Alignment.BottomCenter)
            ) {
                val action = if (hasLastItem) "Remove" else "Add"
                Text("$action Last Item")
            }
        }
        if (hasLastItem) {
            Box(Modifier.weight(1f).fillMaxWidth().background(Color.Cyan))
        }
    }
}

unconsumedWindowInsetsWithPaddingSample

@Composable
fun unconsumedWindowInsetsWithPaddingSample() {
    // This outer Box is representing a 3rd-party layout that you don't control. It has a
    // padding, but doesn't properly use consumeWindowInsets()
    Box(Modifier.padding(10.dp)) {
        // This is the content that you control. You can make sure that the WindowInsets are correct
        // so you can pad your content despite the fact that the parent did not
        // consumeWindowInsets()
        Box(
            Modifier.fillMaxSize() // Force a fixed size on the content
                .recalculateWindowInsets()
                .safeContentPadding()
                .background(Color.Blue)
        )
    }
}

consumeWindowInsetsWithPaddingSample

@Composable
fun consumeWindowInsetsWithPaddingSample() {
    // The outer Box uses padding and properly compensates for it by using consumeWindowInsets()
    Box(
        Modifier.fillMaxSize()
            .padding(10.dp)
            .consumeWindowInsets(WindowInsets(10.dp, 10.dp, 10.dp, 10.dp))
    ) {
        Box(Modifier.fillMaxSize().safeContentPadding().background(Color.Blue))
    }
}
by @alexstyl