Android – default dark mode

Tags: , ,



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

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


Source: stackoverflow