Dark theme is available in Android 10 (API level 29) and higher. It has many benefits:
- Can reduce power usage by a significant amount (depending on the device’s screen technology).
- Improves visibility for users with low vision and those who are sensitive to bright light.
- Makes it easier for anyone to use a device in a low-light environment.
Dark theme applies to both the Android system UI and apps running on the device.
There are three ways to enable Dark theme in Android 10 (API level 29) and higher:
- Use the system setting (Settings -> Display -> Theme) to enable Dark theme.
- Use the Quick Settings tile to switch themes from the notification tray (once enabled).
- On Pixel devices, selecting the Battery Saver mode enables Dark theme at the same time. Other OEMs may or may not support this behavior.
For instructions on applying a dark theme to web-based content using a WebView component, see Darken web content in WebView.
Support Dark theme in your app
In order to support Dark theme, you must set your app's theme (usually found in
res/values/styles.xml
) to inherit from a DayNight
theme:
<style name="AppTheme" parent="Theme.AppCompat.DayNight">
You can also use MaterialComponents' dark theming:
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight">
This ties the app's main theme to the system-controlled night mode flags and gives the app a default Dark theme (when it is enabled).
Themes and styles
Your themes and styles should avoid hard-coded colors or icons intended for use under a light theme. You should use theme attributes (preferred) or night-qualified resources instead.
Here are the two most important theme attributes to know about:
?android:attr/textColorPrimary
This is a general purpose text color. It is near-black in Light theme and near-white in Dark themes. It contains a disabled state.?attr/colorControlNormal
A general-purpose icon color. It contains a disabled state.
We recommend using Material Design
Components, since its color theming
system (such as the theme
attributes ?attr/colorSurface
and ?attr/colorOnSurface
) provides easy access
to suitable colors. Of course, you can customize these attributes in your theme.
Change themes in-app
You might want to allow users to change the app's theme while the app is running. Your app can let the user choose between themes. The recommended options are:
- Light
- Dark
- System default (the recommended default option)
Each of the options map directly to one of the AppCompat.DayNight
modes:
- Light -
MODE_NIGHT_NO
- Dark -
MODE_NIGHT_YES
- System default -
MODE_NIGHT_FOLLOW_SYSTEM
To switch the theme, call
AppCompatDelegate.setDefaultNightMode()
.
Force Dark
Android 10 provides Force Dark, a feature for developers to quickly
implement a Dark theme without explicitly setting a DayNight
theme, as
described above.
Force Dark analyzes each view of your light-themed app, and applies a dark theme automatically before it is drawn to the screen. Some developers use a mix of Force Dark and native implementation to cut down on the amount of time needed to implement Dark theme.
Apps must opt-in to Force Dark by setting android:forceDarkAllowed="true"
in
the activity's theme. This attribute is set on all of the system and AndroidX
provided light themes, such as Theme.Material.Light
. When you use Force Dark,
you should make sure to test your app thoroughly and exclude views as needed.
If your app uses a dark theme (such as Theme.Material
), Force Dark will not
be applied. Similarly, if your app's theme inherits from a DayNight
theme,
Force Dark will not be applied, due to the automatic theme switching.
Disable Force Dark on a view
Force Dark can be controlled on specific views with the android:forceDarkAllowed
layout attribute or with
setForceDarkAllowed()
.
Web content
For information on using dark themes in web-based content, see Darken web content in WebView. For an example of dark theme applied, see the WebView demo on GitHub.
Best practices
The following sections provide best practices for implementing dark themes.
Notifications and Widgets
For UI surfaces that you display on the device but do not directly control, it is important to make sure that any views that you use reflect the host app’s theme. Two good examples are notifications and launcher widgets.
Notifications
Use the system-provided notification templates (such as MessagingStyle
). This
means that the system is responsible for ensuring the correct view styling is
applied.
Widgets and custom notification views
For launcher widgets, or if your app uses custom notification content views, it is important to make sure you test the content on both the Light and Dark themes.
Common pitfalls to look out for:
- Assuming that the background color is always light
- Hardcoding text colors
- Setting a hardcoded background color, while using the default text color
- Using a drawable icon which is a static color
In all of these cases, use appropriate theme attributes instead of hardcoded colors.
Launch screens
If your app has a custom launch screen, it may need to be modified so that it reflects the selected theme.
Remove any hardcoded colors, for example any background colors pointing may be
white. Use the ?android:attr/colorBackground
theme attribute instead.
Note that dark-themed android:windowBackground
drawables only work on Android
10.
Configuration changes
When the app’s theme changes (either through the system setting or AppCompat) it
triggers a uiMode
configuration change. This means that Activities will be automatically recreated.
In some cases you might want an app to handle the configuration change. For example, you might want to delay a configuration change because a video is playing.
An app can handle the implementation of Dark theme itself by declaring that each
Activity can handle the uiMode
configuration change:
<activity
android:name=".MyActivity"
android:configChanges="uiMode" />
When an Activity declares it handles configuration changes, its
onConfigurationChanged()
method will be called when there is a theme change.
To check what the current theme is, apps can run code like this:
Kotlin
val currentNightMode = configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK when (currentNightMode) { Configuration.UI_MODE_NIGHT_NO -> {} // Night mode is not active, we're using the light theme Configuration.UI_MODE_NIGHT_YES -> {} // Night mode is active, we're using dark theme }
Java
int currentNightMode = configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK; switch (currentNightMode) { case Configuration.UI_MODE_NIGHT_NO: // Night mode is not active, we're using the light theme break; case Configuration.UI_MODE_NIGHT_YES: // Night mode is active, we're using dark theme break; }