Search code examples
androidxmlandroid-layoutandroid-support-libraryandroid-theme

AppCompat DayNight theme not work on Android 6.0?


I am using the new Theme.AppCompat.DayNight added in Android Support Library 23.2

On Android 5.1 it works well.

On Android 6.0, activity looks like using light theme, but dialog looks using dark theme.

My Application class:

public class MyApplication extends Application {
    static {
        AppCompatDelegate.setDefaultNightMode(
                AppCompatDelegate.MODE_NIGHT_YES);
    }
}

My styles.xml

<style name="AppTheme" parent="Theme.AppCompat.DayNight">
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
</style>

<style name="Dialog.Alert" parent="Theme.AppCompat.DayNight.Dialog.Alert"/>

My code to show a dialog:

new AlertDialog.Builder(mContext, R.style.Dialog_Alert)
                .setTitle("Title")
                .setMessage("Message")
                .show();

Solution

  • The best solution is to update context with proper config. Here is a snippet of what I do:

    public Context setupTheme(Context context) {
    
        Resources res = context.getResources();
        int mode = res.getConfiguration().uiMode;
        switch (getTheme(context)) {
            case DARK:
                AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
                mode = Configuration.UI_MODE_NIGHT_YES;
                break;
            case LIGHT:
                AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
                mode = Configuration.UI_MODE_NIGHT_NO;
                break;
            default:
                AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO);
                break;
        }
    
        Configuration config = new Configuration(res.getConfiguration());
        config.uiMode = mode;
        if (Build.VERSION.SDK_INT >= 17) {
            context = context.createConfigurationContext(config);
        } else {
            res.updateConfiguration(config, res.getDisplayMetrics());
        }
        return context;
    }
    

    Then use the context in your Application like so

    @Override
    protected void attachBaseContext(Context base) {
        Context context = ThemePicker.getInstance().setupTheme(base);
        super.attachBaseContext(context);
    }