Night mode (aka Dark Theme) enables users to experience UI surfaces, rendered as Android views, in dark colors. All existing or new user-facing features on Chrome Android should implement a night mode variant of the relevant UI surfaces on Milestone M75+.
[TOC]
Colors defined in color_palette.xml and semantic_colors_non_adaptive.xml are independent of night mode (i.e. will not change in night mode), and are used for color references defined in values/semantic_colors_adaptive.xml and values-night/colors.xml.
Color references in values/colors.xml will be used for day mode (aka light theme), and also for night mode if the particular color reference is not defined in values-night/colors.xml. Color references in values-night/colors.xml will be used for night mode.
Example
In most cases, you should make use of the color references that are already defined in //src/ui/android/java/res/values/color_palette.xml and //src/ui/android/java/res/values/semantic_colors_adaptive.xml for your new feature.
However as an example, suppose you got approval from [email protected] to add a new background color.
In //src/ui/android/java/res/values/semantic_colors_non_adaptive.xml, add non-adaptive colors:
<color name="new_bg_color_light">some light background color</color>
<color name="new_bg_color_dark">some dark background color</color>
In //src/ui/android/java/res/values/semantic_colors_adaptive.xml, add adaptive colors in light mode:
<color name="new_bg_color">@color/new_bg_color_light</color>
In //src/ui/android/java/res/values-night/colors.xml, add adaptive colors in night mode:
<color name="new_bg_color">@color/new_bg_color_dark</color>
An example to use this color in XML:
<View
...
android:background="@color/new_bg_color" />
An example to use this color in Java:
mView.setBackgroundResource(R.color.new_bg_color);
mView.setBackgroundColor(
ApiCompatibilityUtils.getColor(mView.getResources(), R.color.new_bg_color));
Optionally, if the color is used exclusively for your feature, or if you want to easily update this color for your feature in the future, in the values/colors.xml that contains colors specifically for your feature, add
<color name="my_shiny_new_feature_bg_color">@color/new_bg_color</color>
If your feature needs colors that don't change based on day/night mode (e.g incognito mode UI), in the values/colors.xml that contains colors specifically for your feature, reference the colors defined in semantic_colors_non_adaptive.xml if possible. If it is not defined in semantic_colors_non_adaptive.xml, ask [email protected] for approval of adding a new color in semantic_colors_non_adaptive.xml. There is no need to define the color reference in values-night/colors.xml.
<!-- Dark background color for my shiny new feature regardless of day/night mode. -->
<color name="my_shiny_new_feature_bg_color_dark">@color/new_bg_color_dark</color>
Colors used in styles can be either adaptive or independent of night mode. When using existing or adding new styles, make sure the colors used in the styles fit your need.
Best practice of naming styles
- If the color adapts for night mode, avoid mentioning a specific color in the style name since it may not be accurate in night mode.
<!-- OK -->
<style name="TextAppearance.Headline.Primary">
<!-- default_text_color is dark grey in day mode, and white in night mode. -->
<item name="android:textColor">@color/default_text_color_list</item>
</style>
<!-- NOT OK -->
<style name="TextAppearance.DarkGreyHeadline">
<!-- default_text_color is dark grey in day mode, and white in night mode. -->
<item name="android:textColor">@color/default_text_color</item>
...
</style>
<!-- OK -->
<style name="TextAppearance.ButtonText.Blue">
<!-- some_blue_color is dark blue in day mode, and light blue in night mode. -->
<item name="android:textColor">@color/some_blue_color</item>
</style>
- If independent of night mode, mention a specific color or where it is generally used. Suffixed by "Light" or "Dark" if the style is inherited from an adaptive style.
<!-- OK -->
<style name="TextAppearance.Body.Incognito">
<item name="android:textColor">@colors/default_text_color_light</item>
...
</style>
<!-- OK -->
<style name="TextAppearance.Headline.Primary.Light">
<item name="android:textColor">@color/default_text_color_light_list</item>
</style>
<style name="TextAppearance.Headline.Primary.Dark">
<item name="android:textColor">@color/default_text_color_dark_list</item>
</style>
If adding a new theme, make sure the parent (or any indirect ancestor) theme of the new theme is one of the MaterialComponents DayNight themes (prefixed with Theme.MaterialComponents.DayNight
), or alternatively, define the same theme in values-night/ with the desired parent theme for night mode. See dark theme in Android developer guide for more details.
- Make sure
View
is inflated fromActivity
context instead ofApplication
contextRemoteView
is an exception. See RemoteViewsWithNightModeInflater.java for details.
- Make sure color resources are accessed from
Activity
orView
context instead ofApplication
context - Check whether
Configuration.uiMode & UI_MODE_NIGHT_MASK
gives the correct UI night mode- If uiMode is not correct, it could be a support library issue or an Android framework issue. You can contact [email protected] for help.
Render tests are the recommended way to verify the appearance of night mode UI. If you are not familiar with render tests, please take a look at render test instructions to learn about how to write a new render test and upload golden images.
For tests using BlankUiTestActivity:
- Put all the render tests into a separate test suite
- Use class parameter
NightModeTestUtils.NightModeParams.class
- Pass in a boolean parameter that indicates night mode state in constructor
- Set up night mode in constructor by calling
NightModeTestUtils#setUpNightModeForBlankUiTestActivity()
andRenderTestRule#setNightModeEnabled()
- During
tearDownTest()
, reset night mode state by callingNightModeTestUtils#tearDownNightModeForBlankUiTestActivity()
See this CL as an example
For tests using ChromeActivityTestRule:
- In the method annotated with
@BeforeClass
, initialize states by callingChromeNightModeTestUtils.setUpNightModeBeforeChromeActivityLaunched()
- Add method
setupNightMode()
with annotation@ParameterAnnotations.UseMethodParameterBefore(NightModeTestUtils.NightModeParams.class)
- In method
setupNightMode()
, set up night mode state by callingChromeNightModeTestUtils#setUpNightModeForChromeActivity()
andRenderTestRule#setNightModeEnabled()
- In the method annotated with
@AfterClass
, reset night mode state by callingtearDownNightModeAfterChromeActivityDestroyed
See this CL as an example
Different ways to turn on night mode:
- Go to Chrome Settings -> Themes on Android L+
- Turn on power save mode (aka battery saver) on Android L+
- Go to Android Settings -> Developer options -> Night mode on Android P
- Go to Android Settings -> Display -> Theme on Android Q
Ways to turn on night mode on custom tab:
- Turn on power save mode (aka battery saver) on Android P+
- Go to Android Settings -> Developer options -> Night mode on Android P
- Go to Android Settings -> Display -> Theme on Android Q
- Set color scheme to
COLOR_SCHEME_DARK
on creating aCustomTabsIntent.Builder
Some tips:
- If building chrome_apk, add
compress_resources = false
in gn args to disable Lemon compression. See Issue 957286 for details. - Night mode is only available on L+
- Animation is turned off when in power save mode on Andoird L-O
Most of the features will follow the app-wise night mode control, but some features might require introduction of an independent night mode control. For example, custom tab will not follow the app-wise night mode control, but instead, will respect the night mode settings from the host app. In such cases, you can
- Create your own implementation of
NightModeStateProvider
- Override
ChromeBaseAppCompatActivity#createNightModeStateProvier()
- Use
AppCompatDelegate#setLocalNightMode()
to update night mode in theConfiguration
of theActivity