Does anyone know why when i'm running under API le...
# compose
m
Does anyone know why when i'm running under API level 35, and using the
Theme.Material3.Light.NoActionBar
, calling the
ComponentActivity.enableEdgeToEdge
function does not actually set the status bar color?
Copy code
DisposableEffect(selected) {
    activity?.enableEdgeToEdge(
        if (selected.isLight) {
            SystemBarStyle.light(selected.color.toArgb(), selected.darkColor.toArgb())
        } else {
            SystemBarStyle.dark(selected.color.toArgb())
        }
    )
    onDispose {

    }
}
Instead i'm having to manually set the color in a surface:
Copy code
Surface(color = selected.color) {
            Surface(
                modifier = Modifier
                    .systemBarsPadding()
                    .navigationBarsPadding()
                    .displayCutoutPadding()
                    .fillMaxHeight()
            ) {
When running under older API levels (say 31), the color changes properly without the outer surface, but the
displayCutoutPadding
does not seem to work.
o
First of all, I change the statusbar color within SideEffect. Then I do it directly in the InsetController. I mean InsetController.isAppearenceLightStatusBar = true/false. It works fine
m
I've got the status bar part working with the proper surface, and it makes sense. What i'm struggling with is the navigation bar (for those that have opted into it). No matter what i do, these icons in the navigation bar are always grey
o
image.png
I can't prove with the video right now. Icons are white. Maybe there are some other conditions in your case
Sorry, you mean navbar
Have you tried that?
h
On API 35 you can't set the status bar colors, they will always be transparent. This is because the methods are deprecated and no-ops on API 35 (https://developer.android.com/reference/android/view/Window#setNavigationBarColor(int) and https://developer.android.com/reference/android/view/Window#setStatusBarColor(int)). I'd recommend to set it to transparent and draw your own status bar / nav bar background to have a consistent experience on both API 35 and below.
m
Ok. So i've got all the other issues licked, but the final issue i'm having is that i can't get the nav bar icons to be white when running under api 35.
Copy code
WindowCompat.getInsetsController(it.window, activity.findViewById(android.R.id.content))
                .isAppearanceLightNavigationBars = isNavigationBarLight
I've debugged this to make sure it's set to false, but the icons are always set as if it's a light nav bar.:
FWIW, under API 31, just setting the nav bar style with
SystemBarStyle.dark
is enough for the buttons to be the proper color (black for a light background, white for a dark background)
Same code running on api 31:
h
If you don't care about anything below API 29, just do this
Copy code
enableEdgeToEdge(
      statusBarStyle = SystemBarStyle.auto(0, 0, { /* dark */ true }),
      navigationBarStyle = SystemBarStyle.auto(0, 0, { /* dark */ true })
   )
No need to muck with the WindowInsetsController api and it will look consistent from 29+. If you want to support lower API levels, I'd copy the scrim values that are in SystemBarStyle.auto() for the navigation bar as well.
SystemBarStyle.dark()
should also work, but it disables the platform scrim on 29+ too so in that case you'd need to add your own scrim. If you go that route, I'd set the scrim colors to transparent too in that case to that everything looks the same on all (reasonable) API levels.
By the way, your nav bar should really be transparent / translucent here with a scrim, not a solid color 😬
m
@hugo I have set it that way. Try running this preview an android 35 emulator
Copy code
@Composable
@Preview(showSystemUi = true, showBackground = true)
private fun StatusBarExample2() {
    fun Context.getComponentActivity(): ComponentActivity? = when (this) {
        is ComponentActivity -> this
        is ContextWrapper -> baseContext.getComponentActivity()
        else -> null
    }

    val backgroundColor = Color(0xFF006851)

    MaterialTheme {
        val activity = LocalContext.current.getComponentActivity()
        SideEffect {
            activity?.enableEdgeToEdge(
                SystemBarStyle.dark(Color.Transparent.toArgb()),
                SystemBarStyle.dark(Color.Transparent.toArgb()),
            )
        }

        Surface(
            color = backgroundColor,
            modifier = Modifier
                .fillMaxSize()
        ) {
            Surface(
                modifier = Modifier
                    .fillMaxSize()
                    .statusBarsPadding()
                    .displayCutoutPadding()
                    .navigationBarsPadding()
            ) {

            }
        }
    }
}
You still get a navigation bar with dark icons:
It's become not much of a big deal for me, because we're going with a light navigation bar, even when the status bar is dark, but there are one or two situations where we have a dark background image that covers the entire screen, and that's where this problem is creeping up for us. If you run the same preview on 31, it's fine
My point is, that either: a. It's broken b. I'm doing something wrong, perhaps in the default XML theme or something
h
Seems to work fine for me on a pixel
m
Maybe it's an emulator issue? Let me try on a pixel 7 pro
h
I did change
Color.Transparent.toArgb()
to 0 though.
m
let me try that too
to be fair, that Color.Transparent.toArgb() should be 0 anyway
h
Shouldn't really matter, it's just a bit weird 😉
exactly
m
yeah, no difference there
h
Maybe an emulator issue. Looks like the content protection isn't being disabled.
m
ok. So yeah, this might be an emulator problem, as it looks correct on a physical device.
image.png
h
yeah without edgeToEdge on a device and setting the theme to force dark navigation bar doesn't seem to work either. On the emulator api 35
m
I so rarely test on physical devices these days unless i'm doing something hardware related (like bluetooth)
h
I always use devices, just for the fidelity of things 😉
But I'm old.
Nice find though 😄
m
I used to as well, but working on a design toolkit, i kinda have to make sure things look correct across a range of api levels and device sizes
And i don't want to have to carry around like 20 devices with me