Change TopAppBar background color from themes.xml

4.9k Views Asked by At

In Jetpack Compose, TopAppBar shows default background color irrespective of what we added to themes.xml.

So how can we change TopAppBar background color from themes.xml so it's applied globally to the App?

TopAppBar(
    title = { Text("Activity") },
    navigationIcon = {
        IconButton(onClick = { onBackPressed() }) {
            Icon(Icons.Filled.ArrowBack, contentDescription = null)
        }
    }
)

themes.xml

<style name="Theme.MyApplication" parent="Theme.MaterialComponents.DayNight">
        <!-- Primary brand color. -->
        <item name="colorPrimary">@android:color/black</item>
        <item name="colorPrimaryVariant">@android:color/holo_orange_dark</item>
        <item name="colorOnPrimary">@android:color/white</item>
</style>

enter image description here

Note : we can change it through backgroundColor attribute of TopAppBar but here I want to achieve it globally.

3

There are 3 best solutions below

0
On BEST ANSWER

For the TopAppBar and the other composables the basis of theming is the MaterialTheme composable and not the AppCompat/MaterialComponents XML themes.

The TopAppBar uses the backgroundColor attribute.
The default value is defined by MaterialTheme.colors.primarySurface.

You can change these colors globally defining your theme adding your Colors and passing them to a MaterialTheme:

private val LightColors = lightColors(
    primary = Yellow500,
    //...
)

Otherwise you can simply use :

TopAppBar(
    title = { Text("Activity") },
    backgroundColor = /*...*/,
    /* ... */
)

If you want to use the AppCompat XML themes in Jetpack Compose you can use the AppCompat Compose Theme Adapter provided by the accompanist library.

2
On

The accepted answer explains what to do adequately. There is one thing you might need to keep in mind, though.

TopAppBar uses MaterialTheme.colors.primarySurface as the background color, and it's defined as the following.

[androidx/compose/material/Colors.kt]
val Colors.primarySurface: Color get() = if (isLight) primary else surface

In other words, if the device is in the light mode, it uses primary, and in the dark mode, it uses surface.

Suppose I have a theme with everything as default values.

private val DarkColorPalette = darkColors()
private val LightColorPalette = lightColors()

@Composable
fun ComposeTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) {
    val colors = if (darkTheme) {
        DarkColorPalette
    } else {
        LightColorPalette
    }

    MaterialTheme(
        colors = colors,
        typography = Typography,
        shapes = Shapes,
        content = content
    )
)

lightColors and darkColors have the following values by default.

fun lightColors(
    primary: Color = Color(0xFF6200EE),
    ...
)

fun darkColors(
    surface: Color = Color(0xFF121212),
    ...
)

When the device is in the light mode, primary (0xFF6200EE) will be TopAppBar's background color.

enter image description here

But when the device is in the dark mode, surface (0xFF121212) is not TopAppBar's background color. It's slightly lighter; 0xFF282828 to be exact.

enter image description here

The reason is TopAppBar has a built-in elevation, which is 4.dp by default.

[androidx/compose/material/AppBar.kt]
@Composable
fun TopAppBar(
    ...
    elevation: Dp = AppBarDefaults.TopAppBarElevation    // 4.dp
) {

This most likely won't cause a problem, but it might matter if you want to apply the exactly same background color to somewhere else, such as setting the same color for the status area's background.

val systemUiController = rememberSystemUiController()
systemUiController.setSystemBarsColor(color = Color(0xFF282828))

enter image description here

Note that for this particular case, it would be easier if you just go full screen and add padding at the top.

WindowCompat.setDecorFitsSystemWindows(window, false)

setContent {
    MyAppTheme {
        Surface(
            modifier = Modifier.systemBarsPadding().fillMaxSize(),    // <--
        ) {
            ...
        }
    }
}
0
On

When you create a new project in studio, you get a file named Theme.kt, in which there are color palettes named lightColors and darkColors. You should modify the parameters of those values to achieve the result globally in your app.