Introduction
With OLED screens becoming more and more common on smartphones, adapting a dark theme to your app can provide a boost to battery life.
In this tutorial, we will learn how to add a dark theme to your native Android app.
Goals
At the end of the tutorial, you would have learned:
- How to modify the dark theme.
- How to switch themes programmatically.
Tools Required
- Android Studio. The version used in this tutorial is Arctic Fox 2020.3.1 Patch 3.
Prerequisite Knowledge
- Basic Android.
Project Setup
To follow along with the tutorial, perform the steps below:
-
Create a new Android project with the default Empty Activity.
-
Extract the
Hello World!
String resource to thestrings.xml
file, sores/values/strings.xml
should have<string name="hello_world">Hello World!</string>
MODE_NIGHT
Flags
The first concept that we need to understand are the MODE_NIGHT
flags.
Inside of the androidx.appcompat.app.AppCompatDelegate
class, there are a few constants prefixed with MODE_NIGHT
, with each representing a flag that determines how your app switches to the dark theme.
MODE_NIGHT_AUTO
: Deprecated. Replaced byMODE_NIGHT_AUTO_TIME
.MODE_NIGHT_AUTO_BATTERY
: Night mode switches on when Battery Saver is enabled.MODE_NIGHT_AUTO_TIME
: Night mode switches on/off depending on the time of day.MODE_NIGHT_FOLLOW_SYSTEM
: Follow the System settings. For example, on my phone (Android 12), this setting can be found at Settings > Display > Appearance > Dark Theme.MODE_NIGHT_NO
: Night mode is switched off.MODE_NIGHT_UNSPECIFIED
: Mostly used withsetLocalNightMode()
to override the default night mode.MODE_NIGHT_YES
: Night mode is turned on.
While it is possible to set these flags programmatically, the Android OS can also control them based on user settings. It is not a requirement to interact with these constants if you just want your app to follow the System settings because your app uses MODE_NIGHT_FOLLOW_SYSTEM
by default.
DayNight
themes
The second concept that we need to be familiar with is the DayNight
themes. To support Dark themes, your App theme must extend Theme.AppCompat.DayNight
or Theme.MaterialComponents.DayNight
.
Theme.AppCompat.DayNight
comes from the androidx.appcompat
library, while Theme.MaterialComponents.DayNight
comes from the com.google.android.material
library.
For this tutorial, the App themes are located under res/values/themes
(Android view).
You will also find another theme file that has the word night in parentheses under res/values/themes
. There is no such directory named themes
in your project, Android Studio automatically groups the theme XML files together in Android view to make the project navigation easy to understand. If you switch back to the Project view, you can see that there are only the values
directory and the values-night
directory.
night
is a legal configuration qualifier name based on this table.
Provide resources for Dark theme
If you want your app to use MODE_NIGHT_FOLLOW_SYSTEM
, then there is no coding required at all. The two most basic steps that you need to take are:
- Have your App theme extend a
DayNight
theme (explained in the previous section). - Provide the Dark theme resources inside a
values-night
directory.
The Empty Activity project created by Android Studio already has Dark theme support.
-
Switch to Android view.
-
Navigate to
res/values/themes
. -
Open
themes.xml
. -
You can see the
DayNight
theme extended by your App theme here.parent="Theme.MaterialComponents.DayNight.DarkActionBar"
The project also provided the resources for the Dark theme with the values-night
qualifier.
- Still under
res/values/themes
, openthemes.xml
(night). - The style name and the parent theme are also exactly the same as the regular theme. There are only a couple of tags with different values. The values in the night version will be used when the Dark theme is turned on.
-
In
res/values/colors.xml
, add a new color called blue with the code#0027FF.
<color name="blue">#0027FF</color>
-
We can modify the Dark theme directly. Open the night
themes.xml
file. -
Add a new attribute with the name
android:colorBackground
and set the value to the blue color that we defined earlier.<item name="android:colorBackground">@color/blue</item>
-
Open
activity_main.xml
in the Design surface. -
Switches to Night mode by pressing the keyboard shortcut N or select the Moon icon located in the Toolbar. This feature allows us to preview the night theme without running the App.
Please note that I am using blue for simplicity only. Real world applications should follow Color and Accessibility guidelines from the design language documentation(Material, Apple HIG, Adobe Spectrum, etc).
Set Dark theme programmatically
It is also possible to set the Night mode programmatically. We just have to call the static function setDefaultNightMode()
from the AppCompatDelegate class.
-
In
MainActivity.kt
, replace the currentonCreate()
function with the code below.override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES) }
-
Normally, you should allow your users to switch the theme with a Switch, but for simplicity, we are just turning the Dark mode on when the App first launches.
Run the app and we will see that it now uses (customized) Dark mode.
Solution Code
MainActivity.kt
package com.example.daniwebdarktheme
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.appcompat.app.AppCompatDelegate
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES)
}
}
colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="blue">#0027FF</color>
</resources>
strings.xml
<resources>
<string name="app_name">Daniweb Dark Theme</string>
<string name="hello_world">Hello World!</string>
</resources>
night/themes.xml
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.DaniwebDarkTheme" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_200</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/black</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_200</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
<item name="android:colorBackground">@color/blue</item>
</style>
</resources>
Summary
We have learned how to modify the dark theme and various ways to switch on the dark mode. The full project code can be found here: https://github.com/dmitrilc/DaniwebDarkTheme