BArtWell
BArtWell

Reputation: 4044

Compose: how to change statusbar color only for specified screen?

I have an application, where all of screens except 2-3 screens have the same statusbar color.

So the purpose is to change statusbar color when this screen is opened and reset statusbar color to default color from theme when this screen is closed.

I am trying to implement it with DisposableEffect:

DisposableEffect(Unit) {
    systemUiController.setStatusBarColor(color = anotherColor)
    onDispose {
        systemUiController.setStatusBarColor(color = defaultColor)
    }
}

It works, but with delays, not synchronously with TopAppBar:

enter image description here

What is the way to implement it correctly?

Upvotes: 4

Views: 2778

Answers (3)

Sadiq Rauf
Sadiq Rauf

Reputation: 179

const isFocused = useIsFocused();

{isFocused ?
<StatusBar backgroundColor='#74ADA2' barStyle='dark-content' />
: 
null}

Upvotes: -1

AagitoEx
AagitoEx

Reputation: 534

I think the delay is inevitable, I've never seen it change instantly.

I always opt-in for a transparent status bar + draw behind systembars and handle everything on my own. And drawing behind system bars is the new recommended approach. Since you are already using compose, this is very easy with help of accompanist lib + compose 1.2.0 has inset modifiers built in to help with this.

request your activity to be laid out edge-to-edge (draw behind system bars)

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    WindowCompat.setDecorFitsSystemWindows(window, false)
}

Using accompanist UIController lib, set status bar colors to transparent.

systemUiController.setSystemBarsColor(
    color = Color.Transparent,
    darkIcons = useDarkIcons
)

In your composables, where needed, consume the appropriate insets.

Modifier.fillMaxSize()
        .statusBarsPadding() //status bar insets
        .navigationBarsPadding() //nav bar insets
        .systemBarsPadding() //both

EDIT: you could create a disposable effect wrapper to switch system icons, and use it everywhere you need. For example: (you can improve this)

@Composable
fun initSystemUi(
    useDarkIcons: Boolean = MaterialTheme.colors.isLight,
    systemUiController: SystemUiController = rememberSystemUiController()
) {
    DisposableEffect(Unit) {
        systemUiController.setSystemBarsColor(
            color = Color.Transparent,
            darkIcons = useDarkIcons
        )
        onDispose {
            systemUiController.setSystemBarsColor(
                color = Color.Transparent,
                darkIcons = useDarkIcons
            )
        }
    }
}

Upvotes: 6

Code Poet
Code Poet

Reputation: 7975

If you are happy to add this code snippet for each of your screens, there will be no delay, as far as I can see on my phone. Basically you set your color locally rather than for the whole app / theme.

val systemUiController = rememberSystemUiController()
SideEffect {
    systemUiController.setStatusBarColor(
        color = aColor
    )
}

Upvotes: 2

Related Questions