Android dark mode adaptation
Android dark mode adaptation
Dark theme
A dark theme is available in Android 10 (API level 29) and higher. Dark themes have many advantages:
- Significantly reduces power consumption (depending on the device's screen technology).
- Improves visibility for users with low vision and those who are sensitive to bright light.
- Make it easier for everyone to use devices in low-light environments.
The dark theme applies to both the Android system interface and the apps running on the device.
Support dark theme in app
To support a dark theme, your app's theme (usually found res/values/styles.xml
at be set to inherit DayNight
the theme:
<style name="AppTheme" parent="Theme.AppCompat.DayNight">
Or MaterialComponent
use the dark theme from :
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight">
This associates the app's primary theme with the system-controlled night mode badge and sets the app's default theme to the dark theme (if enabled).
Themes and styles
Themes and styles should avoid hard-coded colors or icons intended for use with light themes. Theme properties (preferred) or resources suitable for nighttime use should be used instead.
Here are the two most important theme properties to know:
?android:attr/textColorPrimary
This is a general purpose text color. It's close to black in a light theme and close to white in a dark theme. This color contains a disabled state.?attr/colorControlNormal
A generic icon color. This color contains a disabled state.
Force Dark
Android 10 provides the Force Dark feature. This feature allows developers to quickly implement a dark theme without explicitly setting a DayNight theme.
If your app has a light theme, Force Dark analyzes each view of your app and automatically applies a dark theme before the corresponding view is displayed on screen. Some developers mix Force Dark and native implementations to reduce the time it takes to implement a dark theme.
If an app chooses to enable Force Dark, it can be set in its theme background android:forceDarkAllowed="true"
. This property is set on all system and AndroidX provided light themes (eg Theme.Material.Light).
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="android:colorPrimary">@color/colorPrimary</item>
<item name="android:colorAccent">@color/colorAccent</item>
<item name="android:background">@color/colorPrimary</item>
<item name="windowNoTitle">true</item>
<!-- 启用 Force Dark -->
<item name="android:forceDarkAllowed">true</item>
</style>
</resources>
If the app uses a dark theme (such as Theme.Material), the system does not apply Force Dark. Likewise, if the applied theme inherits from the DayNight theme, Force Dark will not be applied because the theme is switched automatically.
Disable Force Dark on the view
You android:forceDarkAllowed
can setForceDarkAllowed()
control Force Dark via layout properties or on specific views.
Android 10 and above
Create a project SDK and select API29: Android 10 or above, and light and dark theme styles will be created in the res directory.
It values/themes.xml
stores the theme of light mode and values-night/themes.xml
the theme of dark mode.
If you want to switch the theme background, you can call it AppCompatDelegate.setDefaultNightMode()
.
configuration changes
A uiMode configuration change is triggered when the app's theme changes (either through system settings or AppCompat). This means that the system automatically recreates the Activity.
In some cases, it may be desirable for an application to handle configuration changes. For example, you might want to delay configuration changes because the device is playing a video.
Apps can declare that each Activity can handle uiMode configuration changes to handle the dark theme implementation itself:
<activity
android:name=".MyActivity"
android:configChanges="uiMode" />
When an Activity declares that it will handle configuration changes, the system calls the Activity's onConfigurationChanged()
methods .
To check which theme is currently in use, an app can run the following code:
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
int currentNightMode = newConfig.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
Log.i(TAG, "onConfigurationChanged: light");
break;
case Configuration.UI_MODE_NIGHT_YES:
// Night mode is active, we're using dark theme
Log.i(TAG, "onConfigurationChanged: dark");
break;
default:
break;
}
}