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:

icon icon

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.

icon icon

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.

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);

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);

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.

android daynight theme_day

 

android daynight theme night

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.

App developer with an eye for design. Loves to create apps with good UI/ UX that doesn’t annoy people. In his spare time, he likes to draw and paint.
Subscribe to stay updated
You'll be first to know about new articles and more. They're sent straight to your inbox!
No Spam, no BS. Promise. You can unsubscribe anytime.

Suleiman

App developer with an eye for design. Loves to create apps with good UI/ UX that doesn't annoy people. In his spare time, he likes to draw and paint.

You may also like...

  • Oezguer Oezkan

    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.

    • Mb Obiosio

      I’m struggling to make this work from preference. Can you help me with the source code for theme settings done from preference screen? cazewonder@gmail.com

      • You can maintain a boolean SharedPreference for night theme. Then apply individually per Activity using getDelegate().setLocalNightMode(mode);
        Just make sure to call recreate() on existing Activities.

      • Mb Obiosio

        Can you just give me the right code practice for that? Thank you. cazewonder@gmail.com

    • Hi there,

      You’re absolutely right. Thanks for keeping an eye out. Post updated accordingly.

  • Shrukul Habib

    Great work.. Thanks for keeping us all updated!

Subscribe to stay updated
You'll be first to know about new articles and more. They're sent straight to your inbox!
No Spam, no BS. Promise. You can unsubscribe anytime.
Gradle setup, ProGuard rules, Material Design palette, metrics and much more

FREE Material Design Starter Project

For more details, click on the below link.
GET IT NOW FOR ANDROID STUDIO!
Download FREE
STARTER PROJECT
Material Design Template Project for Android Studio
DOWNLOAD STARTER PROJECT
Android O is almost here!
Ready your Apps now to get an advantage on Play Store.