Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Programmatically Change Status Bar Text Color in Android 11 (API 30)

I am currently able to update the status bar text color from light to dark using the following inside my base activity:

private fun toggleStatusBarTextColor(light: Boolean) {
    // clear any existing flags
    window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE;
    if(light) {
        window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
    } else {
        window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR)
    }
}

systemUiVisibility is now showing deprecated on API 30, and although the deprecated methods will still function for the time being, I would prefer to replace them with the newer way to accomplish this. I have read that we should now use the WindowInsetsController functions, but it is not clear to be how to accomplish this from the docs. Can someone point me in the right direction?

like image 809
ninehundreds Avatar asked Mar 01 '23 21:03

ninehundreds


2 Answers

For API 30 you can use WindowInsetsController.setSystemBarsAppearance (int appearance, int mask):

To make status bar light:

window.insetsController?.setSystemBarsAppearance(
        WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS,
        WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS
)

To clear the flag:

window.insetsController?.setSystemBarsAppearance(
        0,
        WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS
)

Note that getInsetsController is nullable hence the ? check.

Alternatively (and for lower APIs) you can use WindowInsetControllerCompat:

val windowInsetController = ViewCompat.getWindowInsetsController(window.decorView)
windowInsetController?.isAppearanceLightStatusBars = true // or false

Note: if clearing flag doesn't work check value of window.decorView.windowSystemUiVisibility - if it contains View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR that means your view hierarchy contains a View with this flag which is propagated and affects systemUiVisibility calculation.

like image 115
Pawel Avatar answered Mar 05 '23 18:03

Pawel


I, as others, couldn't get the new API that @Pawel recommended to work on all Android OS versions. I unfortunately found I had to use both the older API as well as the new to get it working on Android 11 & below:

fun setStatusBarLightText(window: Window, isLight: Boolean) {
    setStatusBarLightTextOldApi(window, isLight)
    setStatusBarLightTextNewApi(window, isLight)
}


private fun setStatusBarLightTextOldApi(window: Window, isLight: Boolean) {
    val decorView = window.decorView
    decorView.systemUiVisibility =
        if (isLight) {
            decorView.systemUiVisibility and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv()
        } else {
            decorView.systemUiVisibility or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
        }
}

private fun setStatusBarLightTextNewApi(window: Window, isLightText: Boolean) {
    ViewCompat.getWindowInsetsController(window.decorView)?.apply {
        // Light text == dark status bar
        isAppearanceLightStatusBars = !isLightText
    }
}
like image 29
Sami Avatar answered Mar 05 '23 17:03

Sami