I am using the new Theme.AppCompat.DayNight theme of AppCompat introduced in version 23.2, but instead of switching between a day (light) and night (dark) theme automatically, it always appears as a light theme. How can I get it to switch to a dark theme?
The AppCompat support library provides themes to build apps with the Material Design specification. A theme with a parent of Theme.AppCompat is also required for an Activity to extend AppCompatActivity. The first step is to customize your theme’s color palette to automatically colorize your app. In your app's res/styles.xml you can define:
The DayNight functionality in AppCompat allows your app to easily switch between a dark ⚫ and light ⚪ theme. This has many benefits for your users, from saving power on OLED displays, to increasing usability for people with reduced-vision, and more.
What is use in Android? The AppCompat support library provides themes to build apps with the Material Design specification. A theme with a parent of Theme.AppCompat is also required for an Activity to extend AppCompatActivity.
The ApplicationContext doesn’t have your app theme. You need to pass the Activity, not an Application Context.
As specified in that same 23.2 blog post,
By default, whether it is ‘night’ will match the system value (from UiModeManager.getNightMode())
However, as of now, this effectively means that it is equivalent to MODE_NIGHT_NO
as the only thing that triggers night mode are car docks from the Gingerbread era.
This means that on current devices, the only way to see a dark theme when using a DayNight theme is to use NIGHT_MODE_YES or NIGHT_MODE_AUTO
As stated in both the official post and Chris Banes' post on DayNight, you can change the mode at either the global level or the local level.
The global level relies on the static AppCompatDelegate.setDefaultNightMode()
method, which sets the DayNight mode across your entire app. As this only applies while your process is alive (i.e., it is only an in memory flag), you need to make sure you set it every time your application is started. One recommended approach from Chris' post to do that is to set it in a static method of your custom Application class:
static {
AppCompatDelegate.setDefaultNightMode(
AppCompatDelegate.MODE_NIGHT_...);
}
public class MyApplication extends Application {
If, instead, you only want to change the mode for a single activity/dialog, you can instead call getDelegate().setLocalNightMode()
:
public class MyActivity extends AppCompatActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
// Set the local night mode to some value
getDelegate().setLocalNightMode(
AppCompatDelegate.MODE_NIGHT_...);
// Now recreate for it to take effect
recreate();
}
}
}
This changes just the single instance - you'll note the call to recreate()
- Views that have already been inflated won't be affected by a change in night mode, so you can force the activity to recreate itself to get the updated values.
Of course, Chris' post also states
Also remember that the default is MODE_NIGHT_FOLLOW_SYSTEM, so if we add a user-visible setting to the platform in the future, AppCompat will automatically use it.
There seems to be a bug in Android Lollipop with AppCompat 23.2.0: Google Issue Tracker
The following code does only work pre-Lollipop:
public class MyApplication extends Application {
static {
AppCompatDelegate.setDefaultNightMode(
AppCompatDelegate.MODE_NIGHT_YES);
}
[...]
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With