Hi all, question about system bar colors (content ...
# compose-android
b
Hi all, question about system bar colors (content color, not the [background] color of the system bar itself). I have some screens with a dark TopAppBar, and some screens without a TopAppBar (so just a normal light/white background). How do you change/set the system bar content color "on the fly" based on the content for the current screen? More info in the 🧵
I am using Material 3 theming and
enableEdgeToEdge()
. It's a pretty standard/basic setup, and uses WindowInsets appropriately to display behind system ui's and add appropriate content padding. However, I have screens with various content and need to change the system bar content color, "on the fly". Here's an example (assuming the device is in light mode and I'm using a "light" theme) ... My top level screens contain a
TopAppBar
, while "child" screens do not contain an app bar. My App bar has a dark background color. So when showing a top level screen with an App Bar, I'd like the system bar content to be light/white. But when showing a "child" screen with no App Bar, it's a light background, and so the system bar content should be dark/black.
v
Here's what I'm using to set the status bar theme (via
darkTheme
)
Copy code
val view = LocalView.current
SideEffect {
    val window = (view.context as Activity).window
    val controller = WindowCompat.getInsetsController(window, view)
    controller.isAppearanceLightStatusBars = !darkTheme
}
b
Thanks @Vilgot Fredenberg. I've got that snippet as well. So far, that's the only/best way I've come across to do it. The downside of that approach is that once you use that for one screen, you have to do it for all screens, since the application of the colors to the status bar is "global"/"permanent".
s
Can you not put this in a DisposableEffect so that you can "clear" what you set when you leave this screen?
b
oooh, that's worth a shot
c
Did that end up working @Bradleycorn?
b
@Colton Idle I think so. I haven't tested it out too much yet, but the basic setup works ok. I added an extension method to
MaterialTheme.ColorSheme
to set the status bar content color. It uses a DisposableEffect (as suggested by @Stylianos Gakis) to set the color, and then in it's
onDispose
, it "resets" the color back to whatever it was previously. Here's what it looks like:
Copy code
@Composable
fun ColorScheme.SetStatusBarContentColor(useDarkColor: Boolean) {

        // When previewing in Android studio, the context is not an Activity.
        // In that case, just return, since we can't access the window to set status bar colors.
        val window = (LocalView.current.context as? Activity)?.window ?: return
        val insetsController: WindowInsetsControllerCompat = WindowCompat.getInsetsController(window, window.decorView)

        val initialValue by remember {
            mutableStateOf(insetsController.isAppearanceLightStatusBars)
        }

        DisposableEffect(window) {
           insetsController.isAppearanceLightStatusBars = useDarkColor

            onDispose {
                insetsController.isAppearanceLightStatusBars = initialValue
            }
        }
}
s
You can probably remove the "mutableStateOf" wrapping the initial value. It looks like you never mutate it anyway, so a single remember might be just enough, right?
Also if you change the
useDarkColor
your effect won't re-run again, is that what you want? If you go in there, then switch to dark mode, and then exit the screen does it work as you'd expect it to?
b
You can probably remove the "mutableStateOf" wrapping the initial value
Ah yes, you are correct.
Also if you change the
useDarkColor
your effect won't re-run again, is that what you want?
yeah, that's good enough for me at least for now. I don't need to change "dynamically". I have a
Screen
composable that wraps each of my screens (it does things like fire screen view events for my analytics tracking system, etc). I call it from there to set the status bar content color for that screen. But yeah this would need some adjustments if you needed the content color to change while the same screen/composable is in composition (say like when certain content scrolls or something).
If you go in there, then switch to dark mode, and then exit the screen does it work as you'd expect it to?
yep. So far so good 🤞
🦜 1