运行时更改安卓材质主题



我有一个设置屏幕,用于在运行时更改应用程序主题。我知道如何创建材料设计主题。我在style.xml文件中创建了一个

这是我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>

现在我想将运行时应用程序主题从绿色更改为紫色或黄色。任何人都可以告诉我如何从主题选择中创建颜色选择器,以及如何在style.xml中创建多个主题以将其更改为运行时。

你看过这个演示吗?

多主题材料设计

请参阅此类:

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

查看该演示,它将帮助您了解更多。

使用style.xml的动态主题

这是我的代码

风格.xml

<resources>
    <style name="AppTheme.Base.Green" parent="AppTheme.Green">
        <item name="drawerArrowStyle">@style/DrawerArrowStyle</item>
        <item name="windowActionModeOverlay">true</item>
        <item name="windowActionBarOverlay">true</item>
        <item name="android:windowActionBarOverlay">true</item>
        <item name="android:windowBackground">@color/activity_bg</item>
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>
    <style name="AppTheme.Base.Green.Dark" parent="AppTheme.Green">
        <item name="drawerArrowStyle">@style/DrawerArrowStyle</item>
        <item name="windowActionModeOverlay">true</item>
        <item name="windowActionBarOverlay">true</item>
        <item name="android:windowActionBarOverlay">true</item>
        <item name="android:windowBackground">@color/activity_bg_black</item>
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>
    <style name="AppTheme.Base.Purple" parent="AppTheme.Purple">
        <item name="drawerArrowStyle">@style/DrawerArrowStyle</item>
        <item name="windowActionModeOverlay">true</item>
        <item name="windowActionBarOverlay">true</item>
        <item name="android:windowActionBarOverlay">true</item>
        <item name="android:windowBackground">@color/activity_bg</item>
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>
    <style name="AppTheme.Base.Purple.Dark" parent="AppTheme.Purple">
        <item name="drawerArrowStyle">@style/DrawerArrowStyle</item>
        <item name="windowActionModeOverlay">true</item>
        <item name="windowActionBarOverlay">true</item>
        <item name="android:windowActionBarOverlay">true</item>
        <item name="android:windowBackground">@color/activity_bg_black</item>
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>
    <!-- Base application themes. -->
    <style name="ThemeApp.Green" parent="AppTheme.Base.Green"/>
    <style name="ThemeApp.Green.Dark" parent="AppTheme.Base.Green.Dark"/>
    <style name="ThemeApp.Purple" parent="AppTheme.Base.Purple"/>
    <style name="ThemeApp.Purple.Dark" parent="AppTheme.Base.Purple.Dark"/>

    <style name="DrawerArrowStyle" parent="Widget.AppCompat.DrawerArrowToggle">
        <item name="spinBars">true</item>
        <item name="color">@android:color/white</item>
    </style>

</resources>

主题.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="AppTheme.Green" parent="Theme.AppCompat.Light">
        <item name="colorPrimary">@color/primary_green</item>
        <item name="colorPrimaryDark">@color/primary_dark_green</item>
        <item name="colorAccent">@color/accent_green</item>
        <item name="colorControlHighlight">@color/primary_green</item>
        <item name="android:textColorPrimary">@color/primary_text</item>
        <item name="android:textColorSecondary">@color/secondary_text</item>
    </style>
    <style name="AppTheme.Purple" parent="Theme.AppCompat.Light">
        <item name="colorPrimary">@color/primary_purple</item>
        <item name="colorPrimaryDark">@color/primary_dark_purple</item>
        <item name="colorAccent">@color/accent_purple</item>
        <item name="colorControlHighlight">@color/primary_purple</item>
        <item name="android:textColorPrimary">@color/primary_text</item>
        <item name="android:textColorSecondary">@color/secondary_text</item>
    </style>
</resources>

v21/样式.xml

<resources>
    <style name="AppTheme.Base.Green" parent="AppTheme.Green">
        <item name="drawerArrowStyle">@style/DrawerArrowStyle</item>
        <item name="windowActionModeOverlay">true</item>
        <item name="windowActionBarOverlay">true</item>
        <item name="android:windowActionBarOverlay">true</item>
        <item name="android:windowBackground">@color/activity_bg</item>
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
        <item name="android:navigationBarColor">@color/primary_green</item>
    </style>
    <style name="AppTheme.Base.Green.Dark" parent="AppTheme.Green">
        <item name="drawerArrowStyle">@style/DrawerArrowStyle</item>
        <item name="windowActionModeOverlay">true</item>
        <item name="windowActionBarOverlay">true</item>
        <item name="android:windowActionBarOverlay">true</item>
        <item name="android:windowBackground">@color/activity_bg_black</item>
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
        <item name="android:navigationBarColor">@color/primary_green</item>
    </style>
    <style name="AppTheme.Base.Purple" parent="AppTheme.Purple">
        <item name="drawerArrowStyle">@style/DrawerArrowStyle</item>
        <item name="windowActionModeOverlay">true</item>
        <item name="windowActionBarOverlay">true</item>
        <item name="android:windowActionBarOverlay">true</item>
        <item name="android:windowBackground">@color/activity_bg</item>
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
        <item name="android:navigationBarColor">@color/primary_purple</item>
    </style>
    <style name="AppTheme.Base.Purple.Dark" parent="AppTheme.Purple">
        <item name="drawerArrowStyle">@style/DrawerArrowStyle</item>
        <item name="windowActionModeOverlay">true</item>
        <item name="windowActionBarOverlay">true</item>
        <item name="android:windowActionBarOverlay">true</item>
        <item name="android:windowBackground">@color/activity_bg_black</item>
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
        <item name="android:navigationBarColor">@color/primary_purple</item>
    </style>
    <!-- Base application themes. -->
    <style name="ThemeApp.Green" parent="AppTheme.Base.Green"/>
    <style name="ThemeApp.Green.Dark" parent="AppTheme.Base.Green.Dark"/>
    <style name="ThemeApp.Purple" parent="AppTheme.Base.Purple"/>
    <style name="ThemeApp.Purple.Dark" parent="AppTheme.Base.Purple.Dark"/>

    <style name="DrawerArrowStyle" parent="Widget.AppCompat.DrawerArrowToggle">
        <item name="spinBars">true</item>
        <item name="color">@android:color/white</item>
    </style>

    <!--   <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
       <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />-->
</resources>

更改方法 主题运行时

private void setAppTheme() {
        if (!MainController.preferenceGetString(Theme_Current, "").equals("")) {
            if (MainController.preferenceGetString(Theme_Current, "").equals("Green")) {
                setTheme(R.style.ThemeApp_Green);
            } else if (MainController.preferenceGetString(Theme_Current, "").equals("Green_Dark")) {
                setTheme(R.style.ThemeApp_Green_Dark);
            } else if (MainController.preferenceGetString(Theme_Current, "").equals("Purple_Dark")) {
                setTheme(R.style.ThemeApp_Purple_Dark);
            } else if (MainController.preferenceGetString(Theme_Current, "").equals("Purple")) {
                setTheme(R.style.ThemeApp_Purple);
            }
        } else {
            setTheme(R.style.ThemeApp_Green);
        }
    }

执行此方法后,重新启动所需的活动

完整源代码https://github.com/rkoshti/DynamicMaterialTheme

相关内容

  • 没有找到相关文章