Java – Runtime Change Android Assets theme

Runtime Change Android Assets theme… here is a solution to the problem.

Runtime Change Android Assets theme

I have a settings screen for changing the app theme at runtime. I know how to create Material design themes. I created one in my style.xml file

Here is the code for my style.xml:

 <style name="AppTheme" parent="AppTheme.Base"/>

<style name="AppTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorPrimary">@color/primaryBackground</item>
        <item name="colorPrimaryDark">@color/primaryBackground</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:colorControlNormal">@color/primaryBackground</item>
        <item name="android:colorControlActivated">@color/primaryBackground</item>
        <item name="android:colorControlHighlight">@color/primaryBackground</item>
        <item name="android:textColorPrimary">@color/primaryBackground</item>
        <item name="android:textColorSecondary">@color/primaryBackground</item>
        <item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item>
        <item name="android:textCursorDrawable">@drawable/cursor_indicator</item>
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>

Now I want to change the runtime application theme from green to purple or yellow. Can anyone tell me how to create a color picker from the theme selection and how to create multiple themes in my style.xml to change it to runtime.

Solution

Have you seen this demo?

MultipleThemeMaterialDesign

Check out this class :

public class Preferences {

private static final BoolToStringPref[] PREF_MIGRATION = new BoolToStringPref[]{
            new BoolToStringPref(R.string.pref_dark_theme, false,
                    R.string.pref_theme, R.string.pref_theme_value_red),
    };

public static void sync(PreferenceManager preferenceManager) {
        Map<String, ?> map = preferenceManager.getSharedPreferences().getAll();
        for (String key : map.keySet()) {
            sync(preferenceManager, key);
        }
    }

public static void sync(PreferenceManager preferenceManager, String key) {
        Preference pref = preferenceManager.findPreference(key);
        if (pref instanceof ListPreference) {
            ListPreference listPref = (ListPreference) pref;
            pref.setSummary(listPref.getEntry());
        }
    }

/**
     * Migrate from boolean preferences to string preferences. Should be called only once
     * when application is relaunched.
     * If boolean preference has been set before, and value is not default, migrate to the new
     * corresponding string value
     * If boolean preference has been set before, but value is default, simply remove it
     * @param context   application context
     * TODO remove once all users migrated
     */
    public static void migrate(Context context) {
        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
        SharedPreferences.Editor editor = sp.edit();
        for (BoolToStringPref pref : PREF_MIGRATION) {
            if (pref.isChanged(context, sp)) {
                editor.putString(context.getString(pref.newKey), context.getString(pref.newValue));
            }

if (pref.hasOldValue(context, sp)) {
                editor.remove(context.getString(pref.oldKey));
            }
        }

editor.apply();
    }

public static void applyTheme(ContextThemeWrapper contextThemeWrapper) {
        if (Preferences.darkThemeEnabled(contextThemeWrapper)) {
            contextThemeWrapper.setTheme(R.style.AppTheme_Blue);
        }
    }

private static boolean darkThemeEnabled(Context context) {
        return PreferenceManager.getDefaultSharedPreferences(context)
                .getString(context.getString(R.string.pref_theme),
                        context.getString(R.string.pref_theme_value_red))
                .equals(context.getString(R.string.pref_theme_value_blue));
    }

private static class BoolToStringPref {
        private final int oldKey;
        private final boolean oldDefault;
        private final int newKey;
        private final int newValue;

private BoolToStringPref(@StringRes int oldKey, boolean oldDefault,
                                 @StringRes int newKey, @StringRes int newValue) {
            this.oldKey = oldKey;
            this.oldDefault = oldDefault;
            this.newKey = newKey;
            this.newValue = newValue;
        }

private boolean isChanged(Context context, SharedPreferences sp) {
            return hasOldValue(context, sp) &&
                    sp.getBoolean(context.getString(oldKey), oldDefault) != oldDefault;
        }

private boolean hasOldValue(Context context, SharedPreferences sp) {
            return sp.contains(context.getString(oldKey));
        }
    }
}

Check out the demo, which will help you learn more.

Related Problems and Solutions