Honestly, if you've been building Android apps for more than a minute, you probably remember the days when "full screen" just meant toggling a flag or hiding the status bar for a splash screen. Those days are dead. With Android 15 now enforcing android edge-to-edge for xml layout for any app targeting API 35, the "safe area" isn't a suggestion anymore—it's a requirement.
I’ve seen a lot of developers panic because their perfectly aligned buttons are suddenly buried under a navigation bar. It looks messy. It feels broken. But here’s the thing: making your XML layouts play nice with the system bars isn't actually that hard once you stop fighting the system and start using insets properly.
The Android 15 Reality Check
Basically, if you target Android 15 (API 35), your app is edge-to-edge by default. Period. You can’t opt out. The system ignores your old statusBarColor or navigationBarColor settings in your theme. Instead, it stretches your window from the very top pixel to the very bottom one.
If you don't handle this, your top app bar will hide behind the status bar icons, and your bottom navigation will be a jumbled mess of text and system gesture handles. It’s a bad look.
Stop Using fitsSystemWindows Everywhere
We need to talk about android:fitsSystemWindows="true".
Most people treat this like a magic wand. "Just throw it on the root layout!" they say. Don't do that. It’s kinda unpredictable. When you apply it to a CoordinatorLayout or a DrawerLayout, they often consume the insets and don't pass them down to the children. Or worse, they add padding where you actually wanted your background to bleed through.
For a true edge-to-edge experience, your backgrounds should go behind the bars, but your content (buttons, text, lists) should stay in the safe zone.
The Modern Way: enableEdgeToEdge()
Before you even touch your XML, you’ve got to tell the Activity to let the content flow. The easiest way is using the androidx.activity library.
👉 See also: Siri Class Action Lawsuit: What Really Happened With Your Privacy
Inside your onCreate, before setContentView, just call:
enableEdgeToEdge()
This single line does the heavy lifting of making those system bars transparent and setting up the decor fits. But now comes the part everyone skips: actually handling the insets so your UI doesn't look like an accident.
Handling Insets in XML (The Right Way)
Since we’re talking about android edge-to-edge for xml layout, you’re likely working with ViewCompat. You can't just set a fixed 24dp margin and call it a day because every device has a different notch, a different status bar height, and a different navigation style (3-button vs. gestures).
You’ve got to listen for the insets. Here’s a snippet that actually works:
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main_root)) { v, windowInsets ->
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
// Apply the insets as padding to the view
v.updatePadding(
left = insets.left,
top = insets.top,
right = insets.right,
bottom = insets.bottom
)
// Return the insets so they can continue to propagate if needed
windowInsets
}
This is where the nuance happens. You don't always want to apply all four insets to one view.
💡 You might also like: When Was Three Mile Island? The Stressful Week That Changed Energy Forever
If you have a RecyclerView, you probably want the top inset to apply to your Toolbar (so it sits below the status bar) but the bottom inset to apply to the RecyclerView's bottom padding. This allows the list items to scroll behind the transparent navigation bar—which is the whole point of edge-to-edge—but ensures the last item isn't covered by the system handle.
The Most Common Mistakes
- Forgetting the Keyboard: When the IME (keyboard) pops up, it’s also an inset. If you only account for
systemBars(), your "Send" button will get hidden behind the keyboard. You need to listen forWindowInsetsCompat.Type.ime(). - Hardcoding Heights: Please stop doing this. I’ve seen apps that assume the status bar is 24dp. On a Pixel 8 or a Galaxy S24, that’s just wrong.
- Ignoring the "Chin": On devices with 3-button navigation, the bar is usually opaque or heavily translucent. If you don't handle the bottom inset, your bottom navigation bar might end up twice as tall as it needs to be.
Dealing with Display Cutouts
Notches and punch-holes are the bane of a clean UI. In your theme, you should probably be using:
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
This tells Android, "I know there's a hole in the screen, let me draw there anyway." If you leave it at default, you’ll often get a weird black bar when the phone is in landscape mode. By using shortEdges, your app fills the whole screen, and you use the displayCutout() insets to make sure your "Back" button isn't literally underneath the camera lens.
A Real-World Example: The Floating Action Button (FAB)
Imagine you have a FAB in the bottom right. In a non-edge-to-edge world, it sits 16dp from the bottom. In an edge-to-edge world with gesture navigation, that 16dp puts it right on top of the gesture line.
You need to add the bottom system bar inset to that 16dp.
ViewCompat.setOnApplyWindowInsetsListener(fab) { v, insets ->
val systemBarInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars())
val params = v.layoutParams as ViewGroup.MarginLayoutParams
params.bottomMargin = systemBarInsets.bottom + 16.toPx()
v.layoutParams = params
insets
}
(Note: toPx() is just a helper function you'd write to convert DP to pixels, because Android's inset values are always in raw pixels.)
Why This Matters for 2026
Google is pushing hard for a unified "premium" feel. When an app suddenly has a solid black bar at the top or bottom, it feels like a legacy app from 2018. It feels "crusty."
Using android edge-to-edge for xml layout properly makes your app feel integrated into the hardware. It makes the screen feel larger. Users might not name "insets" as the reason they like your app, but they'll definitely notice if it's missing.
What You Should Do Next
Start by auditing your root layouts. If you see android:fitsSystemWindows="true", try removing it and manually handling the insets with a OnApplyWindowInsetsListener.
Check your themes.xml. If you’re still setting android:statusBarColor, it’s time to move those to a values-v35 folder where you let the system take over. Testing is huge here—don't just test on one emulator. Open the "Display Cutout" settings in Developer Options and try "Tall Cutout" or "Corner Cutout" to see if your UI holds up.
The goal isn't just to "fix" the overlap; it's to embrace the extra screen real estate. Let those beautiful background images bleed into the status bar area. It looks better. Honestly, your users will thank you.
To get started, update your androidx.activity and androidx.core dependencies to the latest versions to ensure enableEdgeToEdge() and WindowInsetsCompat work as expected across all API levels.