Android Dark Theme
Wouldn’t it be great to make the system and apps dark with a single click or even have it turned on automatically? Well, Android 10 makes it much more user-friendly both for the end-user and the developer.
Behaviour
While Dark theme was introduced in Android 10, older devices can take advantage of it!
There are four modes available:
MODE_NIGHT_UNSPECIFIED
-> Unspecified setting.MODE_NIGHT_NO
-> Forces app to turn on Light theme.MODE_NIGHT_YES
-> Forces app to turn on Dark theme.MODE_NIGHT_AUTO_BATTERY
-> Turns on Dark theme when battery optimization is turned on in settings.MODE_NIGHT_FOLLOW_SYSTEM
-> Turns on Dark theme when Dark theme toggle is turned on in settings.- Since
MODE_NIGHT_FOLLOW_SYSTEM
is the only option that does not take effect in Android 9 or older, we can freely use other ones. Google’s recommendations are: - For Android 9 or older ->
MODE_NIGHT_AUTO_BATTERY
. - For Android 10 or newer ->
MODE_NIGHT_FOLLOW_SYSTEM
.
To set a specific mode, all we need to do is to call one static method AppCompatDelegate.setDefaultNightMode(mode)
with one of the modes. The default on all systems is MODE_NIGHT_UNSPECIFIED
, but as we can read in the documentation:
An unspecified mode for night mode. This is primarily used with setLocalNightMode(int)
, to allow the default night mode to be used. If both the default and local night modes are set to this value, then the default value of MODE_NIGHT_FOLLOW_SYSTEM
is applied.
How to support Dark theme
To take advantage of Dark theme in an app, you need to take a few simple steps:
The first one is to replace the parent theme in styles.xml
with Theme.AppCompat.DayNight
when the application is using AppCompat
and Theme.MaterialComponents.DayNight
when using the MaterialComponents
theme.
The next step is to put dark mode-specific resources in a folder with the -night
suffix. For example:
.
└── app
└── src
└── main
└── res
├─ drawable
├─ drawable-night
├─ layout
├─ layout-night
├─ values
└─ values-night
So as you can see, nearly every resource can be different in Dark theme. Below, I have shown how dark mode-specific resources look in Android Studio:
In my example, I used dark mode-specific folders only for drawable
and values
. For the colors I like approach, where I define generic color names in colors.xml
:
<resources>
<color name=„white”>#FFFFFF</color>
<color name=„teal”>#008577</color>
<color name=„aquaDeep”>#00574B</color>
<color name=„amaranth”>#D81B60</color>
<color name=„darkMineShaft”>#222222</color>
<color name=„codGray”>#111111</color>
<color name=„mineShaft”>#303030</color>
<color name=„doveGray”>#646464</color>
</resources>
And then I keep theme-specific colors in different files:
values/app_collors.xml
:
<resources>
<color name=„colorPrimary”>@color/teal</color>
<color name=„colorPrimaryDark”>@color/aquaDeep</color>
<color name=„colorAccent”>@color/amaranth</color>
<color name=„defaultBackgroundColor”>@color/white</color>
<color name=„defaultTextColor”>@color/doveGray</color>
</resources>
values-night/app_collors.xml
:
<resources>
<color name=„colorPrimary”>@color/codGray</color>
<color name=„colorPrimaryDark”>@color/darkMineShaft</color>
<color name=„colorAccent”>@color/amaranth</color>
<color name=„defaultBackgroundColor”>@color/mineShaft</color>
<color name=„defaultTextColor”>@color/white</color>
</resources>
Of course, the same effect can be achieved with theme-specific styles.xml
files, but I think that this approach is a little bit clearer in this scenario.
Preview in Android Studio
To see how the layout looks in dark mode, all you need to do is to check the night
option in the preview settings as shown below:
How to detect current mode
If there is some logic that we want to execute at runtime depending on the current theme, it’s possible to do so with the code snippet below:
val currentNightMode = configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
when (currentNightMode) {
Configuration.UI_MODE_NIGHT_NO -> {} // Night mode is not active
Configuration.UI_MODE_NIGHT_YES -> {} // Night mode is active
}
Example project
Working code can be found in the following repository here.
Summary
As a user, I personally love it when an application supports night mode because it makes applications more comfortable to use in low-light environments. Also, there are power-saving benefits. More and more devices are equipped with OLED screens where pixels are lit individually. Dark pixels are effectively switched off so dark content uses less battery. According to slashgear article using Google Maps dark mode on maximum brightness reduces battery usage by 63% compared to the light version which I think is a really significant benefit.
As a developer, I love the simplicity of adding support for dark mode in the application. In most scenarios, it’s all about arranging the dark mode set of resources to the appropriate folders.
Let me know what you think about new Android features in the comments below.