DayNight Theme Android Tutorial with Example

The DayNight Theme was added to AppCompat with the realease of Support Library v23.2.0. We can reference the theme using Theme.AppCompat.DayNight. DayNight theme allows to switch between light(day) and dark(night) themes, based on the time. Keep in mind that it supports API 14+. Any lower and it defaults to the Light theme.

If you remember, this is just one of the goodies released by this support library version. Another great addition was Bottom Sheets, which you can read about here.

The Old Days

Supporting both Light and Dark themes is pretty popular. It is desirable for any app that focuses on reading.

Doing so requires maintaining two independent themes that inherit from:

  • Theme.AppCompat.Light
  • Theme.AppCompat

Then, you would set the correct Theme in every Activity’s onCreate(), before super().

android night mode theme change

Night mode as seen on Newslet app

 

setTheme(isDarkTheme? R.style.MyDarkTheme : R.style.MyLightTheme);

isDarkTheme is a boolean to check if Dark Theme must be enabled. Ideally, you want users to set this via Settings (SharedPreferences). This is how apps would handle theme switching before, but let’s look at a better alternative.

Using the DayNight Theme

Start by changing your parent theme in values/styles.xml. You can inherit from any of the following themes:

AppCompat DayNight choices

<style name="AppTheme" parent="Theme.AppCompat.DayNight">
<!--Your theme declarations-->
</style>

Next, you  have to tell our app to take advantage of this. Those familiar with switching themes before DayNight, will feel right at home.

We set the theme, immediately in the Activity’s onCreate().

@Override
protected void onCreate(Bundle savedInstanceState) {

    AppCompatDelegate.setDefaultNightMode(
            AppCompatDelegate.MODE_NIGHT_AUTO);

    super.onCreate(savedInstanceState);
...
}

This little method tells your Activity to use the DayNight theme. Notice that we do not use setTheme() anymore. AppCompatDelegate takes care of this.

Wait. What’s AppCompatDelegate?

In short, AppCompatDelegate helps bring Material Design goodness to pre Lollipop Android versions.

It represents a delegate which you can use to extend AppCompat’s support to any Activity. – developer.android.com

The AppCompat support libraries make this possible. That is why our Activities must extend from AppCompatActivity and NOT from Activity.

This medium post tells you how to use AppCompat goodness when not extending from AppCompatActivity.


Let’s get back to the DayNight theme. You would have noticed one more thing in this method call.

AppCompatDelegate.setDefaultNightMode(
 AppCompatDelegate.MODE_NIGHT_AUTO);

That’s right, you may wonder what MODE_NIGHT_AUTO is. The curious one would’ve immediately done a Cmd/Ctrl + Click to read its source.

Let me highlight all available modes, so we can be clear what each one’s for.

  1. MODE_NIGHT_AUTO – The app switches to night theme based on the time. It makes use of location APIs (if necessary permissions granted) for accuracy. Otherwise falls back to using system time.
  2. MODE_NIGHT_FOLLOW_SYSTEM – This is more of an app-wide setting for night mode. Uses the system Night Mode setting to determine if it is night or not.
  3. MODE_NIGHT_NO – Tells the app to never use night mode, regardless of time / location.
  4. MODE_NIGHT_YES –  Tells app to use night mode always, regardless of time / location.

MODE_NIGHT_YES can be used to test Night Theme. This is useful when its not actually night yet. You won’t have to wait the whole day to test it!

Taking Control of DayNight theme

Now that you know how to use the DayNight theme, its time to customize it.

Android allows us to override resources specific to Day or Night themes. You can do this using the –night resource qualifier, appended to our resource folder names.

For instance, I want to change my colors for the night theme. I can do so by creating a new resource, specific for that: res/values-night/colors.xml. Then I can simply override the colors for them here. But for the sake of depth, let’s see how we can override the Night Theme itself.

Create res/values-night/styles.xml. Here we will override the Night Theme.

<style name=“AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
 <item name="colorPrimary">@color/colorPrimaryNight</item>
 <item name="colorPrimaryDark">@color/colorPrimaryDarkNight</item>
 <item name="colorAccent">@color/colorAccentNight</item>
 <item name="android:windowBackground">@color/bg_dark</item>
 </style>

With this setup, we’re overriding Night Theme and specifying a new color scheme for it. You can even specify Night Theme specific drawables.

[su_row][su_column size=”1/2″]

Setting DayNight for a single Activity

You can also apply Activity specific theme using this code snippet.  Use it prior to calling super() in onCreate().

getDelegate().setLocalNightMode(mode);

[/su_column] [su_column size=”1/2″]

Setting DayNight theme for entire app

Set this in your Application class onCreate(). This applies app-wide DayNight theme, depending on mode.

AppCompatDelegate.setDefaultNightMode(mode);

[/su_column] [/su_row]

NOTE:

When referencing resources, always use from AppCompat (your theme). This ensures the correct theme attributes are applied. This ensures the DayNight theme is applied correctly and avoid weird UI issues. Such as black text against a dark background in Night mode. 😉

Result

I’ve applied the DayNight Theme to an existing app. Let’s see how it looks.

[su_row][su_column size=”1/2″]

android daynight theme_day

 

[/su_column] [su_column size=”1/2″]

android daynight theme night

[/su_column] [/su_row]

You’ll notice that I’ve completely changed the Material Design color palette for Night Theme. This is purely for demonstration purposes.

Always remember to completely test both themes across both post and pre Lollipop Android versions. Despite our best attempts to maintain seamless UI, there always might be some issues. No harm in testing 🙂

ALSO READ: Bottom Navigation Bar Android Tutorial

Things to keep in mind

  • Do not use MODE_NIGHT_FOLLOW_SYSTEM by default. As this is system dependent, set to false initially
  • MODE_NIGHT_FOLLOW_SYSTEM can be changed using setLocalNightMode(int). Allow the user to control this via settings, via Preferences
  • Calling AppCompatDelegate.setDefaultNightMode(mode) must be done BEFORE calling super() in Activity onCreate(). Otherwise you must recreate() the Activity for the set theme to take effect
  • Always reference resources and styles from the inherited theme. For example, you must reference primary color in styles as ?attr/colorPrimary and NOT @color/colorPrimary. This ensures correct themed resources are used. It applies to all theme resources. It also eliminates UI inconsistencies, such as non-readable text.

SOURCE CODE: GitHub

Quick Recap

Let’s quickly review what we did.

  1. Make our parent theme extend from any one of Theme.AppCompat.DayNight
  2. Tell our Activity(s) to set DayNight theme depending on the MODE_NIGHT flags
  3. Override night specific theme resources using -night qualifier for folders.
  4. Make sure to reference theme related attributes via styles.
  5. Remember to call recreate() if theme is changed after Activity creation.

Many apps allow switching between Light and Dark themes. But with no official support from Android, we maintained two separate themes.

With DayNight theme, we can inherit from one base style that covers both themes. We can even override night theme and specify different resources. However, using two different themes is a matter of choice for users. Some like to use the Dark Theme when possible. So its a good idea to provide an option for the same.

How do you adapt your UI’s to the DayNight theme? Drop ’em in the comments below. Also don’t forget to subscribe for latest posts and tips.

Suleiman

Product Designer who occasionally writes code.

You may also like...

11 Responses

  1. Thanks a ton for the details.

  2. Kiyan says:

    Thank you for your great tutorial
    I really did not know how to implement night mode to different activities.
    So many thanks again.

  3. korea_navi says:

    I read well. Thank you. Does AppCompatDelegate not support FragmentActivity or Fragment?

  4. AD_LB says:

    Is it possible to use the night-qualifier as the background of the splash screen, before the app starts?
    Meaning as the theme of the “application” tag ?

  5. skiel says:

    How do we have this function with a switch to toggle on/off night mode and at the same time changing the theme of just more than 1 .xml, be it an activity or fragment? Will appreciate it if replied.

  6. Oezguer Oezkan says:

    Sorry if i’m wrong, but i think you made a mistake here. MODE_NIGHT_FOLLOW_SYSTEM doesn’t get it’s value from setLocalNightMode, it just follows the system’s setting.

  7. Shrukul Habib says:

    Great work.. Thanks for keeping us all updated!

Leave a Reply

Your email address will not be published. Required fields are marked *