Skip to content

Edge-to-edge on Android - #116

Open
danielchalmers wants to merge 2 commits into
mainfrom
claude/edge-to-edge-maui-5bb030
Open

Edge-to-edge on Android#116
danielchalmers wants to merge 2 commits into
mainfrom
claude/edge-to-edge-maui-5bb030

Conversation

@danielchalmers

@danielchalmers danielchalmers commented Sep 5, 2026

Copy link
Copy Markdown
Owner

Fixes #110, replaces #107.

The page is now SafeAreaEdges="None" so the BlazorWebView covers the whole window, and app.css pads with env(safe-area-inset-*): the sticky header extends up behind the status bar, the page body and snackbar clear the nav bar, and the dialog container stays inside the safe area (it drops the bottom inset while the keyboard is covering the nav bar so we don't double pad). The old WebKit-only spacer div is gone.

Turns out the SR10 fix for dotnet/maui#14894 was only a template CSS change. What actually made this possible is the WebView: Chromium 136 started forwarding system bar insets to CSS for fullscreen WebViews and 144 does it for all of them, and MAUI passes the insets through untouched when every edge is None. The keyboard problem that killed None last time went away with #114 since the dodge is driven by the visual viewport now.

Bar icons: MAUI picks light or dark icons from the luminance of the theme's colorPrimary, which is a dark purple in both of our modes, so it always lands on light icons. It redoes that on every activity relaunch too (changing nav mode in settings triggers one) and Window.Activated doesn't fire for that, so ApplyPlatformTheme sets both bars itself and is re-run from the Android OnResume lifecycle event. It also turns off the 3-button nav contrast scrim and paints the window background in the surface tone.

Older devices:

  • If the installed WebView is older than 144, MainPage keeps the page letterboxed (SafeAreaRegions.Container) instead of drawing under the bars with no padding. The surface-toned window background is what shows through the transparent bars in that case, which is also what was missing when Blend the system bars into the theme with native safe areas #107 got a black nav bar.
  • On Android 14 and below MAUI still asks for edge-to-edge, but the toolkit's opaque StatusBar.SetColor re-fits the decor, so the system letterboxes the page and draws opaque bars in the surface tone. That's what we want there and it's noted in the code.
  • A WebView older than 80 can't run the app at all (blazor.webview.js and MudBlazor.min.js use optional chaining). Not new, not related, and real Android 8/9 phones get WebView updates up to 137 through Play anyway.

Also bumps MAUI to 10.0.100 and the global.json SDK pin to 10.0.400.

Tested on the API 35 emulator (WebView 150) in light and dark with both nav modes, the note dialog with the keyboard up, an OS theme switch at runtime, and an activity relaunch. Forcing the version guard on the same emulator gives the letterbox with themed bars. On an API 34 emulator with WebView 113 you get the themed opaque bars and the keyboard still works. The API 28 emulator has Chrome 69 so Blazor never starts, which means the pre-Android 11 keyboard path is still untested on a device. 239 tests pass, Android and Windows build. Still needs a run on a real phone before merging.

MAUI 10.0.100 plus a Chromium 136+ WebView forward the system bar insets
into env(safe-area-inset-*), so the page drops the letterbox
(SafeAreaEdges None) and the web UI pads itself. The app now owns the bar
icon contrast on every Android version, disables the 3-button navigation
scrim, tints the still-opaque bars below Android 15, and re-applies all of
that on resume because MAUI resets it whenever the activity relaunches.

Fixes #110
Only WebView 144 and up forwards the system bar insets to CSS, so the page
falls back to the Container safe area when the installed web view is older,
and the window background now carries the surface tone so the transparent
bars still blend behind a letterboxed page. Below Android 15 the toolkit's
opaque status bar color already re-fits the decor, which is the intended
fallback there and is now documented as such.
@danielchalmers

danielchalmers commented Sep 5, 2026

Copy link
Copy Markdown
Owner Author

On why this needs app code at all and whether it's worth waiting for MAUI:

The None + env() part is the intended model, it's what MAUI's own Blazor template does after the SR10 fix. The rest is working around three things.

MAUI has no API for the bar icon color. It guesses from the theme's colorPrimary luminance when it connects a window (wrong for us in light mode), redoes the guess on every activity relaunch, and Window.Activated never fires for that relaunch, hence the OnResume hook. I couldn't find anything upstream that fixes either, so there's nothing to wait for. We could make MAUI's guess right most of the time by setting colorPrimary to the surface tone per light/dark in the Android theme, and then the hook only matters when the in-app theme overrides the OS one.

The WebView version check isn't MAUI's problem. Safe-area insets in WebView came in stages (136 for fullscreen WebViews, 144 for all) and every hybrid framework ends up doing the same check. It can be deleted once 144 is everywhere, probably a year from now.

The bit that's actually fragile is ours: below Android 15 the letterbox is a side effect of the toolkit's StatusBar.SetColor re-fitting the decor. It works and it's commented, but it's incidental. Doing it explicitly through the same page setting the version check uses, and coloring the bars through the window directly, would drop the toolkit from this feature entirely. I'd do that before merging.

Waiting doesn't change much. .NET 11 still forces edge-to-edge on every Android version and dotnet/maui#32498 (None not honored below API 36) is in the backlog. The app side is about forty lines across three files plus the CSS we'd need regardless.

Plan: merge this after the cleanup above, and file two MAUI issues with what came out of this branch (icon appearance overwritten with no API, Activated not raised on relaunch).

@danielchalmers danielchalmers changed the title Go edge-to-edge on Android with native WebView safe-area insets Edge-to-edge on Android Sep 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Theme the system navigation bar for edge-to-edge

1 participant