Developer guide
Common window inset patterns
Edge to edge is the default
Apps that target Android 15 (SDK 35) draw edge to edge by default, and on Android 15 devices LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS is the only cutout mode for non-floating windows. Content can therefore sit under every bar and cutout, so each pattern below decides which inset to respect. Start with Android's edge-to-edge setup for Compose or the Views edge-to-edge guide.
Keeping content off the cutout
Let backgrounds and images fill the screen, and pad text and controls with WindowInsets.safeDrawing, which covers the status bar, navigation bar and cutout together. Use displayCutout alone only when the bars are handled elsewhere. Don't hardcode a status bar height: in landscape the cutout moves to a side edge, which a device page shows when you rotate it. See Display cutouts in Compose and Support display cutouts for Views.
Lists and bottom bars
A list should scroll behind the navigation bar while its first and last items stay reachable. Pass the insets as content padding instead of padding the list itself. Material components such as TopAppBar and NavigationBar apply their own insets, and Scaffold hands the rest to your content (see Material insets in Compose):
Scaffold { innerPadding ->
LazyColumn(
// Scaffold does not consume the insets it passes down.
modifier = Modifier.consumeWindowInsets(innerPadding),
contentPadding = innerPadding,
) {
// Items scroll behind the bars; the first and last stay clear of them.
}
}In Views, apply the bottom inset as the RecyclerView's padding and set clipToPadding="false" for the same effect.
Full-screen video or images
Hide the system bars with WindowInsetsControllerCompat and let users swipe them back temporarily, as described in Hide system bars for immersive mode:
val controller = WindowCompat.getInsetsController(window, window.decorView)
controller.systemBarsBehavior =
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
controller.hide(WindowInsetsCompat.Type.systemBars())Hidden bars report zero insets, but the cutout and gesture zones remain. Keep playback controls inside displayCutout and out of the side gesture zones.
Swipes near the screen edge
In gesture navigation, a swipe from the left or right edge goes back. A seek bar, carousel or drawing canvas that starts at the edge competes with it. Move it inside the systemGestures inset, or opt a small area out with Modifier.systemGestureExclusion() in Compose Foundation or View.setSystemGestureExclusionRects(). The system limits how much of an edge can be excluded, and mandatorySystemGestures, such as the home swipe, can never be excluded. See Gesture navigation and Gesture zones vs. tappable elements.
Custom bottom controls
If you draw your own bottom bar or floating controls, keep tap targets above the tappableElement inset and drag handles out of systemGestures. The bottom navigation inset is small in gesture mode and much taller with 3-button navigation, so check both modes on a device page before shipping a fixed height.
The keyboard
The on-screen keyboard is an inset too. Add Modifier.imePadding() to the screen or field container so text inputs stay visible, as shown in Keyboard animations in Compose. safeDrawing already includes the IME, so a container padded with it needs no extra padding.
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.