I want to implement in my app Dark mode. In default I wish it been following by the system, so in Main Activity I’ve placed:
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
It works fine, but I if user wants to change its mind and select certain option in my app menu to toggle off/on dark mode, activity is restarting and app’s still following system rules. How can I change that?
@Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.action_color_mode) { if(AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES) AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO); else AppCompatDelegate.setDefaultNightMode( AppCompatDelegate.MODE_NIGHT_YES); return true; }
Advertisement
Answer
Code responsible for option you mentioned, is within onCreate(). Mechanism that allows user to change mode is not within onCreate()
public class MainActivityextends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM); } }
When you explicitly change the dark mode, Android recreates the activity and hence calls onCreate
again.
So, after you change the dark mode you won’t notice a change, as AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
is called again when onCreate
is called by the system.
To make this works you can save a value into SharedPreference
that can be checked in onCreate
before setting the system dark mode.
This can be a boolean that you can toggle when you want to manually change the dark mode.
Here is a sample
public class MainActivityextends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); boolean isSystem = prefs.getBoolean("IS_SYSTEM", true); if (isSystem) { AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM); } } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.action_color_mode) { if(AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES) AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO); else AppCompatDelegate.setDefaultNightMode( AppCompatDelegate.MODE_NIGHT_YES); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); prefs.edit().putBoolean("IS_SYSTEM", false).apply(); return true; } }
UPDATE
that works perfect, but when I quit application and then launch again, default system mode is active although I’ve switched it. Is possible here to make it works in that way?
You can use another SharedPreference
boolean to be saved permanently
public class MainActivityextends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); boolean isSystem = prefs.getBoolean("IS_SYSTEM", true); boolean isNight = prefs.getBoolean("IS_NIGHT", false); if (isSystem) { AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM); } else if (isNight) { AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES); } else { AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO); } } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.action_color_mode) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); if (AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES) { AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO); prefs.edit().putBoolean("IS_NIGHT", false).apply(); } else { AppCompatDelegate.setDefaultNightMode( AppCompatDelegate.MODE_NIGHT_YES); prefs.edit().putBoolean("IS_NIGHT", true).apply(); } prefs.edit().putBoolean("IS_SYSTEM", false).apply(); return true; } }