17 KiB
Color Theming
The Material 3 color theming system can be used to create a color scheme that reflects your brand or style.
The Material 3 color theming system uses an organized approach to apply colors to your UI. In this system, theme colors are selected to express different parts of a UI. Material components use these theme colors and their variations to style their individual backgrounds, text, and more.
Design & API Documentation
Using The Color Theming System
All Material 3 components use a Widget.Material3 style, and these styles
reference color attributes from the Material 3 theme (Theme.Material3).
So, it is easy to customize those color attributes across your app by simply
overriding them in your theme. We provide three accent color groups (Primary,
Secondary, Tertiary), each with 4-5 color roles that you can customize to
represent your brand color:
| Design Color Name | Android Attribute | Light Theme Baseline (Dynamic) Color | Dark Theme Baseline (Dynamic) Color |
|---|---|---|---|
| Primary | colorPrimary | #ff6750a4 (system_accent1_600) |
#ffd0bcff (system_accent1_200) |
| On Primary | colorOnPrimary | white (system_accent1_0) |
#ff381e72 (system_accent1_800) |
| Primary Container | colorPrimaryContainer | #ffeaddff (system_accent1_100) |
#ff4f378b (system_accent1_700) |
| On Primary Container | colorOnPrimaryContainer | #ff21005d (system_accent1_900) |
#ffeaddff (system_accent1_100) |
| Inverse Primary | colorPrimaryInverse | #ffd0bcff (system_accent1_200) |
#ff6750a4 (system_accent1_600) |
| Secondary | colorSecondary | #ff625b71 (system_accent2_600) |
#ffccc2dc (system_accent2_200) |
| On Secondary | colorOnSecondary | white (system_accent2_0) |
#ff332d41 (system_accent2_800) |
| Secondary Container | colorSecondaryContainer | #ffe8def8 (system_accent2_100) |
#ff4a4458 (system_accent2_700) |
| On Secondary Container | colorOnSecondaryContainer | #ff1d192b (system_accent2_900) |
#ffe8def8 (system_accent2_100) |
| Tertiary | colorTertiary | #ff7d5260 (system_accent3_600) |
#ffefb8c8 (system_accent3_200) |
| On Tertiary | colorOnTertiary | white (system_accent3_0) |
#ff492532 (system_accent3_800) |
| Tertiary Container | colorTertiaryContainer | #ffffd8e4 (system_accent3_100) |
#ff633b48 (system_accent3_700) |
| On Tertiary Container | colorOnTertiaryContainer | #ff31111d (system_accent3_900) |
#ffffd8e4 (system_accent3_100) |
By changing these color attributes, you can easily change the styles of all the Material components to which your theme is applied.
The Material Design color theming system provides additional colors which don't represent your brand, but define your UI and ensures accessible color combinations. These additional color attributes are as follows:
| Design Color Name | Android Attribute | Light Theme Baseline (Dynamic) Color | Dark Theme Baseline (Dynamic) Color |
|---|---|---|---|
| Error | colorError | #ffb3261e (Same) |
#fff2b8b5 (Same) |
| On Error | colorOnError | white (Same) |
#ff601410 (Same) |
| Error Container | colorErrorContainer | #fff9dedc (Same) |
#ff8c1d18 (Same) |
| On Error Container | colorOnErrorContainer | #ff410e0b (Same) |
#fff2b8b5 (Same) |
| Outline | colorOutline | #ff79747e (system_neutral2_500) |
#ff938f99 (system_neutral2_400) |
| Background | android:colorBackground | #fffffbfe (system_neutral1_10) |
#ff1c1b1f (system_neutral1_900) |
| On Background | colorOnBackground | #ff1c1b1f (system_neutral1_900) |
#ffe6e1e5 (system_neutral1_100) |
| Surface | colorSurface | #fffffbfe (system_neutral1_10) |
#ff1c1b1f (system_neutral1_900) |
| On Surface | colorOnSurface | #ff1c1b1f (system_neutral1_900) |
#ffe6e1e5 (system_neutral1_100) |
| Surface Variant | colorSurfaceVariant | #ffe7e0ec (system_neutral2_100) |
#ff49454f (system_neutral2_700) |
| On Surface Variant | colorOnSurfaceVariant | #ff49454f (system_neutral2_700) |
#ffcac4d0 (system_neutral2_200) |
| Inverse Surface | colorSurfaceInverse | #ff313033 (system_neutral1_800) |
#ffe6e1e5 (system_neutral1_100) |
| Inverse On Surface | colorOnSurfaceInverse | #fff4eff4 (system_neutral1_50) |
#ff313033 (system_neutral1_800) |
Using Surface Colors
Material 3 involves using primary colored elevation overlays to present visual
hierarchy with different elevations in both light and dark themes. Material 3
themes enable this by default with setting ?attr/elevationOverlayColor to
?attr/colorPrimary.
In order to facilitate some orchestration around the elevation overlays, we have the following theme attributes:
| Attribute Name | Description | Default Value |
|---|---|---|
elevationOverlayEnabled |
Whether the elevation overlay functionality is enabled. | true |
elevationOverlayColor |
The color used for the elevation overlays, applied at an alpha based on elevation. | colorPrimary |
If inheriting from the Theme.Material3 theme or a descendant, you most likely
do not have to set these attributes yourself because the Material themes already
set up the above defaults.
The elevation overlays will be applied upon surface colors and create various
tonal variations of surface colors. Within the Material 3 color palette, we have
five predefined surface tonal variations (Surface1-5) which are used as the
default surface colors (by applying different elevations) of different
Material 3 components. However, these surface tonal colors are NOT
implemented as color resources but their actual color values are calculated
on the fly with the given ?attr/elevationOverlayColor, as mentioned above.
In a practical scenario, you have three ways to include those tonal surface colors in your app:
Material Design Components
The easiest way is using Material Design Components with built-in support of tonal surface colors/elevation overlays. You can customize surface colors of those components by changing their elevation.
The following is a list of Material components that support elevation overlays.
Those components has colorSurface set as the default background color and can
be elevated:
- Top App Bar
- Bottom App Bar
- Bottom Navigation
- Button
- Floating Action Button
- Chip
- Tabs
- Card
- Dialog
- Menu
- Bottom Sheet
- Navigation Drawer
- Switch
- Date Picker
- Time Picker
SurfaceColors enums
If using Material Design Components is not an option in your use case, you may want to consider getting those tonal surface colors on the fly, by using the convenient enums we provide in Material Library. For example, if you want to get the color hex value of Surface1, you can do:
int colorSurface1 = SurfaceColors.SURFACE_1.getColor(context);
This will return the calculated tonal surface color corresponding to the
Surface1 definition and your ?attr/elevationOverlayColor setting in your
themes.
MaterialShapeDrawable or ElevationOverlayProvider (advanced)
If you have a more complicated use case than the above ones, you can check if
com.google.android.material.shape.MaterialShapeDrawable
or
com.google.android.material.elevation.ElevationOverlayProvider
would serve your needs. These two classes provide a set of APIs to help you
calculate and render blended colors according to different background colors and
elevations, with the same elevation overlay formula we are using across
the Material libraries. Note that we suggest you use them carefully to ensure
a consistent look and feel of your app.
Using dynamic colors
Starting from Android S, the framework provides the ability to support dynamic colors in your UI based on the user's wallpaper or color choice on the device.
To apply dynamic colors, the Material 3 library provides 3 theme overlays to be used upon the base Material 3 themes:
ThemeOverlay.Material3.DynamicColors.LightThemeOverlay.Material3.DynamicColors.DarkThemeOverlay.Material3.DynamicColors.DayNight(select day/night mode automatically.)
To make implementing dynamic color solutions easier, the Material 3 library
provides a helper class to apply dynamic colors:
com.google.android.material.color.DynamicColors.
There are several ways to use this helper class according to different
scenarios:
Apply dynamic colors to all activities in the app
In your application class’ onCreate() method, call:
DynamicColors.applyToActivitiesIfAvailable(this);
This will register an ActivityLifeCycleCallbacks to your application and will
attempt to apply the dynamic color theme overlay specified by
R.attr.dynamicColorThemeOverlay in your app/activity theme in the
onActivityPreCreated() callback method, if the app is running on Android S+.
By default R.attr.dynamicColorThemeOverlay will be
ThemeOverlay.Material3.DynamicColors.Light/Dark if you are using Material 3
themes.
You can also have finer control over applying the theme overlay by providing a precondition when calling the method:
DynamicColors.applyToActivitiesIfAvailable(this, (activity, themeResId) -> {
// ...implement your own logic here. Return `true` if dynamic colors should be applied.
});
Or provide your own customized dynamic color theme overlays, likely inheriting from the Material3 theme overlays above, by doing:
DynamicColors.applyToActivitiesIfAvailable(this, R.style.ThemeOverlay_MyApp_DynamicColors_DayNight);
Note that if you are applying your own non-dynamic theme overlays to override Material colors in certain activities, fragments, layouts, etc., the dynamic colors will be overwritten by your theme overlays as well because dynamic colors are applied before activities are created. If that’s not the desired behavior you want, you will need to either stop overriding Material colors in your theme overlays or customize them with a proper dynamic color definition.
Apply dynamic colors to a specific activity
You can also opt to only apply dynamic colors to a few specific activities, by
calling the below method in your activities’ onCreate() method (or before you
inflate anything from it):
DynamicColors.applyIfAvailable(this);
If the app is running on Android S+, dynamic colors will be applied to the activity. You can also apply with a custom theme overlay or with a precondition as depicted above in the application section.
Apply dynamic colors to a specific fragment/view
To apply dynamic colors only to a few of the views in an activity is less straightforward. If you have to do that, the easiest solution would be creating a themed context to create the view. We provide a helper method for this purpose:
context = DynamicColors.wrapContextIfAvailable(context);
This method will return a context with the dynamic color theme overlay applied, if dynamic colors are available on the device.
Note that no matter which approach you follow, you will have to have M3 base
themes (e.g.,Theme.Material3.DayNight.NoActionBar) applied first to make
dynamic color theme overlays work, becaue they use all of the same color theme
attributes.
Custom Colors
Material 3 uses purple-ish colors as the default accent colors if dynamic colors are not available. If you need different brand colors in your app, you may want to define custom colors for your theme. Keep in mind that the default Material 3 styles generally use colors in the following combinations:
| Container Color | Content Color |
|---|---|
| Surface / Surface Variant | On Surface / On Surface Variant / Primary / |
: : Secondary / Error : | Primary | On Primary | | Primary Container | On Primary Container | | Secondary | On Secondary | | Secondary Container | On Secondary Container | | Tertiary | On Tertiary | | Tertiary Container | On Tertiary Container |
So if changing one of the above colors, you may want to change their relevant colors as well to maintain the visual consistency and the contrast requirement of Material components.
These color theme attributes can be customized in your theme that inherits from
one of the "baseline" Theme.Material3.* themes, and dynamic color theme
overlays (ThemeOverlay.Material3.DynamicColors.*), can be applied on top
of your customized "baseline" theme.
[Important] Be careful to maintain the same luminance level when creating custom colors so the contrast requirement won't be broken. For example, since the default Primary color in light theme has a luminance level of 40, it would be best to use a luminance level of 40 with your custom Primary color as well, in order to avoid accidentally breaking the contrast requirement in certain components.
Defining custom colors
When creating your app colors, do not use the same name as the color slot:
<resources>
<color name="color_primary">...</color>
<color name="color_surface">...</color>
</resources>
Instead use literal names relevant to the RGB value. Eg:
<resources>
<color name="brand_blue">...</color>
<color name="brand_grey">...</color>
</resources>
Theming an Individual Component
If you want to change the color of just one instance of a component without
tweaking theme-level attributes, this can be done by creating a new component
style that extends from a Widget.Material3 style.
For example, if you want to change MaterialButton so that it uses
colorSecondary for its background tint rather than the default color, all you
need to do is define your own button style that extends from a Material Design
style and set the mapping yourself:
<style name="Widget.MyApp.Button" parent="Widget.Material3.Button">
<item name="backgroundTint">?attr/colorSecondary</item>
</style>
You would then apply the Widget.MyApp.Button style to any buttons you want to
have this alternate style.
Theming All Instances of One Component
If, however, you want to change the default styles for all instances of a
component, e.g. MaterialButton, this is possible by modifying the
materialButtonStyle attribute in your theme.
<style name="Theme.MyApp" parent="Theme.Material3.Light.NoActionBar">
...
<item name="materialButtonStyle">@style/Widget.MyApp.Button</item>
...
</style>
This will set the default style of any MaterialButtons in your app to
Widget.MyApp.Button. Similar default style attributes exist for most other
components, e.g. tabStyle, chipStyle, textInputStyle, and so on.
Theme Attribute Mapping
All MDC-Android components have been updated to use the theme attributes described above, when applicable.
To understand how the high-level theme attributes map to specific parts of each component, please refer directly to the component's documentation.