Night theme

From Android API 29+ themes support night/day modes. Advantages of night mode:

  • reduce power usage by a significant amount, this depends on the device’s screen technology
  • improve visibility for users with low vision and those who are sensitive to bright light
  • makes it easier for anyone to use a device in a low-light environment.

Night mode is also known as black mode, dark theme and light-on-dark.

User has three ways to enable night mode outside from your app:

  • using the system setting (Settings -> Display -> Theme)
  • using the Quick Settings tile to switch themes from the notification tray
  • selecting the Battery Saver mode on some devices such as Pixel

To support night mode, inherit your app's theme from a DayNight theme or its subthemes.

<style name="AppTheme" parent="Theme.AppCompat.DayNight">
...
</style>

<!-- Or you can use Theme.MaterialComponents.DayNight -->

Setup attributes of theme for day mode in values/style.xml. And setup attributes for night mode in values-night/style.xml

There are the two most important theme attributes:

  • ?android:attr/textColorPrimary - a general purpose text color. It is near-black in light theme and near-white in dark themes. It contains a disabled state.
  • ?attr/colorControlNormal - a general-purpose icon color. It contains a disabled state. You can use it as tint color for the outlined vector drawables to automatically adjust color.
  • ?attr/colorControlActivated - the color applied to icons/controls in their activated state (e.g. checked). You can use it as tint color for the filled vector drawables to automatically adjust color.
  • ?attr/colorControlHighlight - the color applied to control highlights (e.g. ripples, list selectors).
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:tint="?android:colorControlNormal" ... 

AppCompatDelegate class defines constants that are used to set night mode flag for activity:

  • MODE_NIGHT_NO - select light mode
  • MODE_NIGHT_YES - select dark mode
  • MODE_NIGHT_FOLLOW_SYSTEM - select the system's night mode
  • MODE_NIGHT_AUTO_BATTERY - same as MODE_NIGHT_FOLLOW_SYSTEM for APIs 14-28

Call setDefaultNightMode() method of AppCompatDelegate class in activity to apply night or day mode. This method automatically restarts all started Activities, so call it before super.onCreate() method.

override fun onCreate(savedInstanceState: Bundle?) {
 
    AppCompatDelegate.setDefaultNightMode(
                          AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
    super.onCreate(savedInstanceState)
    
    // ...
}

Apply the theme to the activities as usual in the Manifest.xml file or programmatically.

Check current value of the night mode flag

configuration changes

An activity can handle the implementation of dark theme itself. For this declare that activity can handle the uiMode configuration change in Manifest.xml file:

<activity
    android:name=".MyActivity"
    android:configChanges="uiMode" />

Override onConfigurationChanged() method of activity.

Example of onConfigurationChanged()
override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)

    val currentNightMode = newConfig.uiMode and Configuration.UI_MODE_NIGHT_MASK
    
    when (currentNightMode) {
        Configuration.UI_MODE_NIGHT_NO -> {} // nigh mode is not active
        Configuration.UI_MODE_NIGHT_YES -> {} // night mode is active
    }
    // ...
}

old way

There is old way to emulate day/night mode that is used before API 29.

Create light theme from Theme.AppCompat.Light theme or its subthemes.

Create dark theme from Theme.AppCompat theme or its subthemes.

Save the value of night mode in shared preference or somewhere else.

Assign necessary theme programmatically.

override fun onCreate(savedInstanceState: Bundle?) {
    
    val isDarkTheme = readNightModeFlag()
    val theme = if(isDarkTheme) R.style.MyAppDarkTheme else R.style.MyAppLightTheme
    setTheme(theme)
    
    super.onCreate(savedInstanceState)
    
    // ...
}