windowinsets.info

Developer guide

Window insets in Compose and Views

Jetpack Compose

Compose is Android's recommended UI toolkit, so its examples come first. If your app still uses XML layouts, the View-based equivalents follow below.

In Compose, WindowInsets.safeDrawing is the union of systemBars, displayCutout and ime. With the keyboard hidden it equals the Safe Area Insets shown on each device page, so those values are what this padding resolves to on that model.

Opting in to edge-to-edge

Apps targeting Android 15 (API 35) are drawn edge-to-edge by default. Call enableEdgeToEdge() so older versions behave the same, then pad content yourself:

Kotlin
class MainActivity : ComponentActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    enableEdgeToEdge()
    super.onCreate(savedInstanceState)
    setContent {
      Box(
        Modifier
          .fillMaxSize()
          .background(MaterialTheme.colorScheme.surface) // drawn behind the bars
          .windowInsetsPadding(WindowInsets.safeDrawing) // or .safeDrawingPadding()
      ) {
        Content()
      }
    }
  }
}

With Material 3 Scaffold

Scaffold places its bars inside the insets and hands the remaining space to the content as innerPadding. Pass contentWindowInsets explicitly so the cutout is included in landscape:

Kotlin
Scaffold(
  topBar = { TopAppBar(title = { Text("Inbox") }) },
  floatingActionButton = { FloatingActionButton(onClick = {}) { Icon(Icons.Default.Add, null) } },
  contentWindowInsets = WindowInsets.safeDrawing,
) { innerPadding ->
  LazyColumn(
    modifier = Modifier.consumeWindowInsets(innerPadding),
    contentPadding = innerPadding, // list scrolls behind the bars, last item stays reachable
  ) {
    items(messages) { MessageRow(it) }
  }
}

Picking the right inset type

  • safeDrawing: keep text and images from being covered by bars, the cutout or the keyboard.
  • safeGestures: keep draggable controls out of the system gesture zones.
  • safeContent: both of the above, for content that is visible and interactive.
  • displayCutout alone: full-bleed media that only needs to avoid the camera.

Reading the values

Kotlin
val density = LocalDensity.current
val layoutDirection = LocalLayoutDirection.current
val safe = WindowInsets.safeDrawing

val topPx = safe.getTop(density)                       // Int, px
val padding = safe.asPaddingValues()                   // PaddingValues, dp
val startDp = padding.calculateStartPadding(layoutDirection)

Views: reading insets in your Activity or Fragment

With ViewCompat (Jetpack, recommended)

Use ViewCompat.setOnApplyWindowInsetsListener:

Kotlin
ViewCompat.setOnApplyWindowInsetsListener(rootView) { view, insets ->
  val statusBars = insets.getInsets(Type.statusBars())
  val navBars = insets.getInsets(Type.navigationBars())
  val cutout = insets.getInsets(Type.displayCutout())

  // Apply padding: view.setPadding(
  //   statusBars.left, statusBars.top,
  //   statusBars.right, navBars.bottom
  // )

  insets  // return unhandled insets to others
}

Direct API access

On API 29+, use WindowInsets.getInsets(). On newer APIs (31+), also check Display.getRoundedCorner().

Views: safe areas for content

Safe area = system bars + display cutout. Combine them to find where content is always visible and tappable:

Kotlin
val systemBars = insets.getInsets(Type.systemBars())
val cutout = insets.getInsets(Type.displayCutout())
val safe = Insets.of(
  max(systemBars.left, cutout.left),
  max(systemBars.top, cutout.top),
  max(systemBars.right, cutout.right),
  max(systemBars.bottom, cutout.bottom)
)

Found an issue or want to contribute?

Open an issue or pull request on GitHub. If you have a device and want to add insets data, use InsetsProbe and share your JSON.