Android Native - How to set Dark Theme

dimitrilc 2 Tallied Votes 200 Views Share

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:

  1. How to modify the dark theme.
  2. How to switch themes programmatically.

Tools Required

  1. Android Studio. The version used in this tutorial is Arctic Fox 2020.3.1 Patch 3.

Prerequisite Knowledge

  1. Basic Android.

Project Setup

To follow along with the tutorial, perform the steps below:

  1. Create a new Android project with the default Empty Activity.

  2. Extract the Hello World! String resource to the strings.xml file, so res/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.

  1. MODE_NIGHT_AUTO: Deprecated. Replaced by MODE_NIGHT_AUTO_TIME.
  2. MODE_NIGHT_AUTO_BATTERY: Night mode switches on when Battery Saver is enabled.
  3. MODE_NIGHT_AUTO_TIME: Night mode switches on/off depending on the time of day.
  4. 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.
  5. MODE_NIGHT_NO: Night mode is switched off.
  6. MODE_NIGHT_UNSPECIFIED: Mostly used with setLocalNightMode() to override the default night mode.
  7. 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).

themes.png

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.

values.png

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:

  1. Have your App theme extend a DayNight theme (explained in the previous section).
  2. Provide the Dark theme resources inside a values-night directory.

The Empty Activity project created by Android Studio already has Dark theme support.

  1. Switch to Android view.

  2. Navigate to res/values/themes.

  3. Open themes.xml.

  4. 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.

  1. Still under res/values/themes, open themes.xml (night).
  2. 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.

compare.png

  1. In res/values/colors.xml, add a new color called blue with the code #0027FF.

     <color name="blue">#0027FF</color>
  2. We can modify the Dark theme directly. Open the night themes.xml file.

  3. 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>
  4. Open activity_main.xml in the Design surface.

  5. 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.

preview.png

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.

  1. In MainActivity.kt, replace the current onCreate() function with the code below.

     override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES)
     }
  2. 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.

blue_app.png

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

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.