All Ruby on Rails Node JS Android iOS React Native Frontend Flutter QA

Android Dark Theme

Introduction

Android 10 brings us lots of new features. In my opinion, one of the most interesting is the Dark theme. Most likely everyone would agree that using very bright applications at night is uncomfortable. Some apps support more eye-friendly themes at night, but every application needs to be configured separately. 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:

android_dark_mode_1

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:

android_dark_mode_2

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

android_dark_mode_3

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.

 

Photo by NASA on Unsplash

New call-to-action
Looking for new opportunities? Check our offers!
READ ALSO FROM Mobile
Read also
Need a successful project?
Estimate project or contact us