Nathan
Nathan

Reputation: 78439

Jetpack Compose: Top app bar scroll behavior not changing status bar color

I've implemented the pinned top app bar scroll container, and it works for changing the app bar color on scroll, however the status bar color isn't affected at all.

Here's what I have:

val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())

Scaffold(
    Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
    topBar = {
        // just a wrapper for CenterAlignedTopAppBar
        StandardTopAppBar("Home", scrollBehavior = scrollBehavior)
    }
){ ... }

If it's relevant, in order to detect if the soft keyboard is present, I enabled:

WindowCompat.setDecorFitsSystemWindows(window, false)

And my status bar color in initially set in my Theme. It was set to primary color when I autogenerated the project in android studios, but I changed it to surface color to match the appbar standards:

if (!view.isInEditMode) {
        SideEffect {

            (view.context as Activity).window.statusBarColor = colorScheme.surface.toArgb()
            //(view.context as Activity).window.statusBarColor = colorScheme.primary.toArgb()
            ViewCompat.getWindowInsetsController(view)?.isAppearanceLightStatusBars = !darkTheme // changed from just darkTheme
        }
    }

tl;dr; top app bar color changes on scroll, but status bar does not. What is the correct pattern to use here? I looked through some of the pinnedScrollBehavior code, and I don't see anything that would invoke status bar changes, so I'm wondering if I'm supposed to have the status bar be transparent and change the insets for the appbar? Or should I manually hook into the scroll logic and change the color myself? Any help is appreciated!

Upvotes: 6

Views: 3166

Answers (2)

Kelvin Kirwa
Kelvin Kirwa

Reputation: 91

This is the problem i had until i found this solution here : I used a Scaffold composable, which eccepts : an appBar, content, bottom bar etc . in the scaffold , i added the following :

    Scaffold(
      
     topBar = {
                     TopAppBar(
                         title = { Text(text = "#Composers", color = 
                     MaterialTheme.colorScheme.primary)
                     },
                         modifier= 
                     Modifier.background(MaterialTheme.colorScheme.primary),
                         scrollBehavior= scrollBehavior
                     )
    
            },
        contentWindowInsets = ScaffoldDefaults
            .contentWindowInsets
            .exclude(WindowInsets.navigationBars)
            .exclude(WindowInsets.ime)
    ) {
        /* Your Scaffold  composable content  here, for example in my case , i had the following Column  */

paddingValues ->
       Column(
            Modifier
                .fillMaxSize()
                .padding(paddingValues)
                .imePadding()
                .systemBarsPadding()
){
  /* Your Column composable content chere,*/
}

    }

By doing so , the App bar will be adjusted to ensure that it also appears below the status bar making the color appear on nested scroll behaviour.

Upvotes: 1

Amal
Amal

Reputation: 439

In Theme.kt, inside the YourAppTheme() function add.

WindowCompat.setDecorFitsSystemWindows(window, false)

Doing this will display contents below StatusBar and NavigationBar* ( Only on older versions of Jetpack Compose. In newer versions, PaddingValues are correctly set by default. ).

Now set the StatusBar and NavigationBar color to Color.Transparent.

// make sure to use the compose color package, not the default one
import androidx.compose.ui.graphics.Color

window.statusBarColor = Color.Transparent.toArgb()
window.navigationBarColor = Color.Transparent.toArgb()

You also need to make sure that the padding values for the direct child of Scaffold() are correctly set using the padding values passed in the callback from the Scaffold() composable.

Set the correct StatusBar and NavigationBar icon colors for the theme.

WindowCompat.getInsetsController(window, window.decorView).isAppearanceLightStatusBars = !darkTheme

WindowCompat.getInsetsController(window, window.decorView).isAppearanceLightNavigationBars = !darkTheme

If you're using ModalBottomSheetLayout or BottomSheetScaffold, you also need to set Insets inside your BottomSheet composable to prevent NavigationBar from overlapping app content using,

Modifier.windowInsetsPadding(WindowInsets.navigationBars)

Edit

In Material3, window.setDecorFitsSystemWindows() is only compatible > API Level 30.

Use WindowCompat.setDecorFitsSystemWindows(window, false) for backwards compatibility.

Upvotes: 8

Related Questions