Direct code

public class DarkModeUtils {

    public static final String KEY_CURRENT_MODEL = "night_mode_state_sp";

    private static int getNightModel(Context context) {
        SharedPreferences sp = context.getSharedPreferences(KEY_CURRENT_MODEL, Context.MODE_PRIVATE);
        return sp.getInt(KEY_CURRENT_MODEL, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
    }

    public static void setNightModel(Context context, int nightMode) {
        SharedPreferences sp = context.getSharedPreferences(KEY_CURRENT_MODEL, Context.MODE_PRIVATE);
        sp.edit().putInt(KEY_CURRENT_MODEL, nightMode).apply();
    }

    /**
     * ths method should be called in Application onCreate method
     *
     * @param application application
     */
    public static void init(Application application) {
        int nightMode = getNightModel(application);
        AppCompatDelegate.setDefaultNightMode(nightMode);
    }

    /**
     * 应用夜间模式
     */
    public static void applyNightMode(Context context) {
        AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
        setNightModel(context, AppCompatDelegate.MODE_NIGHT_YES);
    }

    /** * Apply daytime mode */
    public static void applyDayMode(Context context) {
        AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
        setNightModel(context, AppCompatDelegate.MODE_NIGHT_NO);
    }

    /** * Dynamic switch is required to follow the system theme */
    public static void applySystemMode(Context context) {
        AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
        setNightModel(context, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
    }

    /** * Determine if the App is currently in dark mode **@paramContext *@returnReturns the * /
    public static boolean isDarkMode(Context context) {
        int nightMode = getNightModel(context);
        if (nightMode == AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) {
            int applicationUiMode = context.getResources().getConfiguration().uiMode;
            int systemMode = applicationUiMode & Configuration.UI_MODE_NIGHT_MASK;
            return systemMode == Configuration.UI_MODE_NIGHT_YES;
        } else {
            returnnightMode == AppCompatDelegate.MODE_NIGHT_YES; }}}Copy the code

Using the process

Obviously, this is the way to switch to dark mode. Before calling, you must select the dark style of your App.

How to fit

  1. Create a values-night folder and replace all the colors used in the page with those in dark mode.
  2. Create a new mipMAP-Night/Drawable – Night folder and replace the image and style resources used in the page with the corresponding resources in dark mode.
  3. Status bar The last method in the top code isDarkMode determines what color of the status bar to display. It’s better to do it in BaseActivity, otherwise it’s too much Activity.
  4. Call the method above the call to switch the App to dark mode. Points to note are as follows:

Need to pay attention to

  1. Just call it on androidx. Support, and switching dark mode in an Activity requires dynamically calling the activity.recreate() method. For specific reasons see the following source code:
/**
     * Sets the default night mode. This is the default value used for all components, but can
     * be overridden locally via {@link #setLocalNightMode(int)}.
     *
     * <p>This is the primary method to control the DayNight functionality, since it allows
     * the delegates to avoid unnecessary recreations when possible.</p>
     *
     * <p>If this method is called after any host components with attached
     * {@link AppCompatDelegate}s have been 'started', a {@code uiMode} configuration change
     * will occur in each. This may result in those components being recreated, depending
     * on their manifest configuration.</p>
     *
     * <p>Defaults to {@link #MODE_NIGHT_FOLLOW_SYSTEM}.</p>
     *
     * @see #setLocalNightMode(int)
     * @see #getDefaultNightMode()
     */
    public static void setDefaultNightMode(@NightMode int mode) {
        switch (mode) {
            case MODE_NIGHT_NO:
            case MODE_NIGHT_YES:
            case MODE_NIGHT_FOLLOW_SYSTEM:
            case MODE_NIGHT_AUTO_TIME:
            case MODE_NIGHT_AUTO_BATTERY:
                if(sDefaultNightMode ! = mode) { sDefaultNightMode = mode; applyDayNightToActiveDelegates(); }break;
            default:
                Log.d(TAG, "setDefaultNightMode() called with an unknown mode");
                break; }}Copy the code

Support version:

public static void setDefaultNightMode(int mode) {
        switch(mode) {
        case -1:
        case 0:
        case 1:
        case 2:
            sDefaultNightMode = mode;
            break;
        default:
            Log.d("AppCompatDelegate"."setDefaultNightMode() called with an unknown mode"); }}Copy the code

After comparison, we can find that after switching the dark mode of androidx, I actively call the apply method to make the Activity rebuild. It’s not on support, it’s just an assignment. So use on the Support version requires calling the activity.recreate() method yourself.