Search code examples
androidmaterial-designandroid-toolbarandroid-theme

Android, set Toolbar style in theme.xml file


I am trying to customize the look of Toolbar in my app.

Target
I would like to set the title color and the background color of the Toolbar.
I read about how Theme and Style works, so I was able to try some solutions. I found out that title color is managed by app:titleTextColor property and the background color from the android:background attribute.


Premise
To know how to act it is necessary to know how the style of the widget that we need to modify is managed.

The base Toolbar style is defined in the Widget.MaterialComponents.Toolbar style as below.

<style name="Widget.MaterialComponents.Toolbar" parent="Widget.AppCompat.Toolbar">
    <item name="titleTextAppearance">?attr/textAppearanceHeadline6</item>
    <item name="titleTextColor">?android:attr/textColorPrimary</item>
    <item name="subtitleTextAppearance">?attr/textAppearanceSubtitle1</item>
    <item name="subtitleTextColor">?android:attr/textColorSecondary</item>
    <!-- Overrides minimum height in landscape to avoid headline6 and subtitle1 height concerns. -->
    <item name="android:minHeight">@dimen/mtrl_toolbar_default_height</item>
    <item name="maxButtonHeight">@dimen/mtrl_toolbar_default_height</item>
</style>

Here the value of titleTextColor is set to ?android:attr/textColorPrimary.


So my first attempt was simply to add the ovverride of android:textColorPrimary attribute in my app theme.

<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
    <!-- Primary brand color. -->
    <item name="colorPrimary">@color/purple_500</item>
    <item name="colorPrimaryVariant">@color/purple_700</item>
    <item name="colorOnPrimary">@color/white</item>
    <!-- Secondary brand color. -->
    <item name="colorSecondary">@color/teal_200</item>
    <item name="colorSecondaryVariant">@color/teal_700</item>
    <item name="colorOnSecondary">@color/black</item>
    <!-- Status bar color. -->
    <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>

    <!-- Customize your theme here. -->
    <item name="android:textColorPrimary">@color/white</item>
</style>

Result: This works.

To also set the background I decided to create a custom Toolbar style where to put the background definition, so I changed my theme as below.

<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
    ...    
    <!-- Customize your theme here. -->
    <item name="toolbarStyle">@style/MyToolbarStyle</item>
</style>
<style name="MyToolbarStyle" parent="Widget.MaterialComponents.Toolbar">
    <item name="android:textColorPrimary">@color/white</item>
    <item name="android:background">?attr/colorPrimary</item>
</style>

Result: This does not works. The android:background is applied but the android:textColorPrimary not.

Setting the value of titleTextColor directly inside MyToolbarStyle works.

<style name="MyToolbarStyle" parent="Widget.MaterialComponents.Toolbar">
    <item name="titleTextColor">?attr/colorOnPrimary</item>
    <item name="android:background">?attr/colorPrimary</item>
</style>

I also tried to set the toolbar theme where I override the Android attribute:textColorPrimary, as below.

<style name="Base_ToolbarStyle" parent="Widget.MaterialComponents.Toolbar">
    <item name="android:background">?attr/colorPrimary</item>
    <item name="android:theme">@style/Base_ToolbarTheme</item>
</style>

<style name="Base_ToolbarTheme">
    <item name="android:textColorPrimary">@color/white</item>
    <item name="android:textColorSecondary">@color/white</item>
</style>

Result: This does not works too.

Now I am a bit confused from the outcome of my tests.

Why is it not possible to override the android:textColorPrimary in the custom style?


Solution

  • To apply a style you can use (and the toolbarStyle attribute applies this style to all the Toolbar) the style attribute:

       <androidx.appcompat.widget.Toolbar
             style="@style/MyToolbarStyle"
    

    with:

    <style name="MyToolbarStyle" parent="Widget.MaterialComponents.Toolbar">
        <item name="titleTextColor">?attr/colorOnPrimary</item>
        <item name="android:background">?attr/colorPrimary</item>
    </style>
    

    because titleTextColor is a property defined in the Toolbar.

    To apply a theme overlay you can use the android:theme attribute:

       <androidx.appcompat.widget.Toolbar
            android:theme="@style/MyToolbarThemeOverlay"
    

    with

    <style name="MyToolbarThemeOverlay">
        <item name="android:textColorPrimary">@color/white</item>
    </style>
    

    because android:textColorPrimary is an attribute defined at theme level.

    If you want to override a theme attribute directly in a style you have to use the materialThemeOverlay attribute:

    <style name="MyToolbarStyle" parent="Widget.MaterialComponents.Toolbar">
        <item name="android:background">?attr/colorPrimary</item>
        <item name="materialThemeOverlay">@style/MyToolbarThemeOverlay</item>
    </style>