android
android copied to clipboard
Make the navigation bar and status bar transparent (edge-to-edge)
Is your feature request related to a problem? Please describe. Both the navigation bar and the status bar are solid colors and do not allow for other elements to go under them, making the application feel less polished.
Describe the solution you'd like Making the application display edge-to-edge content, as described here: https://developer.android.com/develop/ui/views/layout/edge-to-edge
Describe alternatives you've considered, if any Not applicable.
Additional context
Example of an app handling edge-to-edge incorrectly (notice how the side menu goes under the navigation bar and the status bar):
Example of an app handling edge-to-edge correctly (notice how the side menu goes under both the navigation bar and the status bar, since they are truly transparent):
Unfortunately this isn't as easy as you might think because of the WebView. Last time I tried the problem was that information about insets wasn't set correctly on the WebView, making it impossible for the frontend to adapt. That means content will end up behind the system navigation, which is especially problematic when using button navigation or when you have a tall status bar due to a camera/cutout. It looks like the bug is still unresolved: https://issuetracker.google.com/issues/40699457.
(I thought we already had an issue for this, but can't find it.)
Ah well that sucks, it would have been neat. Let's hope Google does something about it.
What do you think about passing this inset values from android activity to webview on page load? I created a quick demo in Android Compose:
Scaffold (modifier = Modifier.fillMaxSize()) { padding ->
AndroidView(
factory = { context ->
WebView(context).apply {
settings.javaScriptEnabled = true
webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
val safeInsetTop = (padding.calculateTopPadding().value)
val safeInsetBottom = (padding.calculateBottomPadding().value)
val safeAreaJs = """
document.documentElement.style.setProperty('--android-safe-area-inset-top', '${safeInsetTop}px');
document.documentElement.style.setProperty('--android-safe-area-inset-bottom', '${safeInsetBottom}px');
""".trimIndent()
evaluateJavascript(safeAreaJs, null)
}
}
}
},
update = { webView ->
webView.loadUrl("http://10.0.2.2:8000")
},
)
}
In above snippet we can see that Scaffold component (edge-to-edge) give us padding property (our insets) and we are executing JS after page load that sets css properties.
Then HA page instead of relying on env() can have custom property that works on both android and ios.
:root {
--insets-top: var(--android-safe-area-inset-top, env(safe-area-inset-top));
--insets-bottom: var(--android-safe-area-inset-bottom, env(safe-area-inset-bottom));
}
.main {
padding-top: var(--insets-top);
}
.bottom {
position: fixed;
bottom: 0;
padding-bottom: var(--insets-bottom);
background-color: white;
display: block;
width: 100%;
}
Below we can see that text have proper padding on top and bottom of screen
This looks a bit hacked together to me but considering how the WebView still doesn't do inset support correctly (it now kinda works on first load, but breaks after navigation) if the frontend team is OK, I think we can consider it as well.
Not as easy as you might think however because HA/frontend version is decoupled from the app and users might have multiple servers on different HA versions.