Android动态设置主题(使用RxBus模式)

原文发表于 Android猿

之前写过一篇文章:RxBus的实现及简单使用。今天我们尝试使用RxBus动态切换主题。

一、定义主题颜色

color.xml

    <color name="red_primary">#F44336</color>
    <color name="red_primary_dark">#D32F2F</color>
    <color name="red_accent">#F44336</color>

    <color name="pink_primary">#E91E63</color>
    <color name="pink_primary_dark">#C2185B</color>
    <color name="pink_accent">#E91E63</color>

    <color name="brown_primary">#795548</color>
    <color name="brown_primary_dark">#5D4037</color>
    <color name="brown_accent">#795548</color>


    <color name="blue_primary">#2196F3</color>
    <color name="blue_primary_dark">#1976D2</color>
    <color name="blue_accent">#2196F3</color>

    <color name="blue_grey_primary">#607D8B</color>
    <color name="blue_grey_primary_dark">#455A64</color>
    <color name="blue_grey_accent">#607D8B</color>

    <color name="yellow_primary">#FFEB3B</color>
    <color name="yellow_primary_dark">#FBC02D</color>
    <color name="yellow_accent">#FFEB3B</color>

    <color name="deep_purple_primary">#673AB7</color>
    <color name="deep_purple_primary_dark">#512DA8</color>
    <color name="deep_purple_accent">#673AB7</color>


    <color name="green_primary">#4CAF50</color>
    <color name="green_primary_dark">#388E3C</color>
    <color name="green_accent">#4CAF50</color>

    <color name="deep_orange_primary">#FF5722</color>
    <color name="deep_orange_primary_dark">#E64A19</color>
    <color name="deep_orange_accent">#FF5722</color>

    <color name="grey_primary">#9E9E9E</color>
    <color name="grey_primary_dark">#616161</color>
    <color name="grey_accent">#9E9E9E</color>

    <color name="cyan_primary">#00BCD4</color>
    <color name="cyan_primary_dark">#0097A7</color>
    <color name="cyan_accent">#00BCD4</color>

    <color name="amber_primary">#FFC107</color>
    <color name="amber_primary_dark">#FFA000</color>
    <color name="amber_accent">#FFC107</color>

    <color name="primary">#2196F3</color>
    <color name="primary_dark">#1E88E5</color>
    <color name="accent">@color/primary</color>

二、定义主题样式

styles.xml

   <style name="RedTheme" parent="AppTheme">
        <item name="colorPrimary">@color/red_primary</item>
        <item name="colorPrimaryDark">@color/red_primary_dark</item>
        <item name="colorAccent">@color/red_accent</item>
    </style>

    <style name="PinkTheme" parent="AppTheme">
        <item name="colorPrimary">@color/pink_primary</item>
        <item name="colorPrimaryDark">@color/pink_primary_dark</item>
        <item name="colorAccent">@color/pink_accent</item>
    </style>

    <style name="BrownTheme" parent="AppTheme">
        <item name="colorPrimary">@color/brown_primary</item>
        <item name="colorPrimaryDark">@color/brown_primary_dark</item>
        <item name="colorAccent">@color/brown_accent</item>
    </style>


    <style name="BlueTheme" parent="AppTheme">
        <item name="colorPrimary">@color/blue_primary</item>
        <item name="colorPrimaryDark">@color/blue_primary_dark</item>
        <item name="colorAccent">@color/blue_accent</item>
    </style>


    <style name="BlueGreyTheme" parent="AppTheme">
        <item name="colorPrimary">@color/blue_grey_primary</item>
        <item name="colorPrimaryDark">@color/blue_grey_primary_dark</item>
        <item name="colorAccent">@color/blue_grey_accent</item>
    </style>


    <style name="YellowTheme" parent="AppTheme">
        <item name="colorPrimary">@color/yellow_primary</item>
        <item name="colorPrimaryDark">@color/yellow_primary_dark</item>
        <item name="colorAccent">@color/yellow_accent</item>
    </style>


    <style name="DeepPurpleTheme" parent="AppTheme">
        <item name="colorPrimary">@color/deep_purple_primary</item>
        <item name="colorPrimaryDark">@color/deep_purple_primary_dark</item>
        <item name="colorAccent">@color/deep_purple_accent</item>
    </style>


    <style name="GreenTheme" parent="AppTheme">
        <item name="colorPrimary">@color/green_primary</item>
        <item name="colorPrimaryDark">@color/green_primary_dark</item>
        <item name="colorAccent">@color/green_accent</item>
    </style>

    <style name="DeepOrangeTheme" parent="AppTheme">
        <item name="colorPrimary">@color/deep_orange_primary</item>
        <item name="colorPrimaryDark">@color/deep_orange_primary_dark</item>
        <item name="colorAccent">@color/deep_orange_accent</item>
    </style>

    <style name="GreyTheme" parent="AppTheme">
        <item name="colorPrimary">@color/grey_primary</item>
        <item name="colorPrimaryDark">@color/grey_primary_dark</item>
        <item name="colorAccent">@color/grey_accent</item>
    </style>

    <style name="CyanTheme" parent="AppTheme">
        <item name="colorPrimary">@color/cyan_primary</item>
        <item name="colorPrimaryDark">@color/cyan_primary_dark</item>
        <item name="colorAccent">@color/cyan_accent</item>
    </style>

    <style name="AmberTheme" parent="AppTheme">
        <item name="colorPrimary">@color/amber_primary</item>
        <item name="colorPrimaryDark">@color/amber_primary_dark</item>
        <item name="colorAccent">@color/amber_accent</item>
    </style>

三、在需要的地方弹出主题选择对话框

private void showThemeChooseDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
        builder.setTitle("设置主题");
        Integer[] res = new Integer[]{R.drawable.red_round, R.drawable.brown_round, R.drawable.blue_round,
                R.drawable.blue_grey_round, R.drawable.yellow_round, R.drawable.deep_purple_round,
                R.drawable.pink_round, R.drawable.green_round, R.drawable.deep_orange_round,
                R.drawable.grey_round, R.drawable.cyan_round};
        List<Integer> list = Arrays.asList(res);
        ColorsListAdapter adapter = new ColorsListAdapter(MainActivity.this, list);
        adapter.setCheckItem(MyThemeUtils.getCurrentTheme(MainActivity.this).getIntValue());
        GridView gridView = (GridView) LayoutInflater.from(MainActivity.this).inflate(R.layout.colors_panel_layout, null);
        gridView.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);
        gridView.setCacheColorHint(0);
        gridView.setAdapter(adapter);
        builder.setView(gridView);
        final AlertDialog dialog = builder.show();
        gridView.setOnItemClickListener(
                new AdapterView.OnItemClickListener() {
                    @Override
                    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                        dialog.dismiss();
                        int value = MyThemeUtils.getCurrentTheme(MainActivity.this).getIntValue();
                        if (value != position) {
                            PreferenceUtils.getInstance(MainActivity.this).saveParam("change_theme_key", position);
                            changeTheme(MyThemeUtils.Theme.mapValueToTheme(position));
                        }
                    }
                }

        );
    }
对话框圆形颜色选项

在drawable下新建red_round.xml,其他主题颜色类似

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
    <solid android:color="@color/red_primary"/>
</shape

四、ColorsListAdapter、colors_image_layout.xml,主题选择框中颜色适配器及其xml

ColorsListAdapter

public class ColorsListAdapter extends BaseAdapter {

    private int checkItem;
    Context context;
    List<Integer> list;

    public ColorsListAdapter(Context context, List<Integer> list) {
        this.context = context;
        this.list = list;
    }


    @Override
    public int getCount() {
        return list.size();
    }

    @Override
    public Object getItem(int position) {
        return list.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Holder holder;
        if (convertView == null) {
            convertView = LayoutInflater.from(context).inflate(R.layout.colors_image_layout, null);
            holder = new Holder();
            holder.imageView1 = (ImageView) convertView.findViewById(R.id.img_1);
            holder.imageView2 = (ImageView) convertView.findViewById(R.id.img_2);
            convertView.setTag(holder);
        } else {
            holder = (Holder) convertView.getTag();
        }
        holder.imageView1.setImageResource(list.get(position));
        if (checkItem == position) {
            holder.imageView2.setImageResource(R.drawable.ic_done_white);
        }
        return convertView;
    }
    public void setCheckItem(int checkItem) {
        this.checkItem = checkItem;
    }
    static class Holder {
        ImageView imageView1;
        ImageView imageView2;
    }
}

colors_image_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:background="@android:color/transparent"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
    <ImageView
        android:id="@+id/img_1"
        android:layout_gravity="center"
        android:layout_width="40dp"
        android:layout_height="40dp" />
    <ImageView
        android:id="@+id/img_2"
        android:layout_gravity="center"
        android:layout_width="20dp"
        android:layout_height="20dp" />
</FrameLayout>

五、使用RxBus发布事件和处理事件

发布

 private void changeTheme(MyThemeUtils.Theme theme) {
       RxBus.getInstance().post(new RxbusEvent(theme));
    }

接收

rxSbscription=RxBus.getInstance().toObserverable(RxbusEvent.class)
                .subscribe(new Action1<RxbusEvent>() {
                    @Override
                    public void call(RxbusEvent rxbusEvent) {
                        changeTheme(rxbusEvent.getTheme());
                    }
                });

六、用到的工具类

PreferenceUtils

public class PreferenceUtils {
    private SharedPreferences sharedPreferences;

    private SharedPreferences.Editor shareEditor;

    private static PreferenceUtils preferenceUtils = null;

    public static final String NOTE_TYPE_KEY = "NOTE_TYPE_KEY";

    public static final String EVERNOTE_ACCOUNT_KEY = "EVERNOTE_ACCOUNT_KEY";

    public static final String EVERNOTE_NOTEBOOK_GUID_KEY = "EVERNOTE_NOTEBOOK_GUID_KEY";

    private PreferenceUtils(Context context){
        sharedPreferences = context.getSharedPreferences("ThemeSetting", Context.MODE_PRIVATE);
        shareEditor = sharedPreferences.edit();
    }

    public static PreferenceUtils getInstance(Context context){
        if (preferenceUtils == null) {
            synchronized (PreferenceUtils.class) {
                if (preferenceUtils == null) {
                    preferenceUtils = new PreferenceUtils(context.getApplicationContext());
                }
            }
        }
        return preferenceUtils;
    }

    public String getStringParam(String key){
        return getStringParam(key, "");
    }

    public String getStringParam(String key, String defaultString){
        return sharedPreferences.getString(key, defaultString);
    }

    public void saveParam(String key, String value)
    {
        shareEditor.putString(key,value).commit();
    }

    public boolean getBooleanParam(String key){
        return getBooleanParam(key, false);
    }

    public boolean getBooleanParam(String key, boolean defaultBool){
        return sharedPreferences.getBoolean(key, defaultBool);
    }

    public void saveParam(String key, boolean value){
        shareEditor.putBoolean(key, value).commit();
    }

    public int getIntParam(String key){
        return getIntParam(key, 0);
    }

    public int getIntParam(String key, int defaultInt){
        return sharedPreferences.getInt(key, defaultInt);
    }

    public void saveParam(String key, int value){
        shareEditor.putInt(key, value).commit();
    }

    public long getLongParam(String key){
        return getLongParam(key, 0);
    }

    public long getLongParam(String key, long defaultInt){
        return sharedPreferences.getLong(key, defaultInt);
    }

    public void saveParam(String key, long value){
        shareEditor.putLong(key, value).commit();
    }

    public void removeKey(String key){
        shareEditor.remove(key).commit();
    }
}

MyThemeUtils

public class MyThemeUtils {

    public static void changTheme(Activity activity, Theme theme) {
        if (activity == null)
            return;
        int style = R.style.RedTheme;
        switch (theme) {
            case BROWN:
                style = R.style.BrownTheme;
                break;
            case BLUE:
                style = R.style.BlueTheme;
                break;
            case BLUE_GREY:
                style = R.style.BlueGreyTheme;
                break;
            case YELLOW:
                style = R.style.YellowTheme;
                break;
            case DEEP_PURPLE:
                style = R.style.DeepPurpleTheme;
                break;
            case PINK:
                style = R.style.PinkTheme;
                break;
            case GREEN:
                style = R.style.GreenTheme;
                break;
            case DEEP_ORANGE:
                style = R.style.DeepOrangeTheme;
                break;
            case GREY:
                style = R.style.GreyTheme;
                break;
            case CYAN:
                style = R.style.CyanTheme;
                break;
            case AMBER:
                style = R.style.AmberTheme;
                break;
            default:
                break;
        }
        activity.setTheme(style);
    }

    public static Theme getCurrentTheme(Context context) {
        int value = PreferenceUtils.getInstance(context)
                .getIntParam("change_theme_key", 0);
        return MyThemeUtils.Theme.mapValueToTheme(value);
    }

    public enum Theme {
        RED(0),
        BROWN(1),
        BLUE(2),
        BLUE_GREY(3),
        YELLOW(4),
        DEEP_PURPLE(5),
        PINK(6),
        GREEN(7),
        DEEP_ORANGE(8),
        GREY(9),
        CYAN(10),
        AMBER(11);

        private int mValue;

        Theme(int value) {
            this.mValue = value;
        }

        public static Theme mapValueToTheme(final int value) {
            for (Theme theme : Theme.values()) {
                if (value == theme.getIntValue()) {
                    return theme;
                }
            }
            // If run here, return default
            return RED;
        }

        static Theme getDefault() {
            return RED;
        }

        public int getIntValue() {
            return mValue;
        }
    }
}

基类BaseActivity,主题的初始化。注意,需要变换主题的Activity需继承BaseActivity

public class BaseActivity extends AppCompatActivity {
    protected PreferenceUtils preferenceUtils;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        preferenceUtils = PreferenceUtils.getInstance(this);
        initTheme();
        super.onCreate(savedInstanceState);
    }

    private void initTheme() {
        MyThemeUtils.Theme theme = MyThemeUtils.getCurrentTheme(this);
        MyThemeUtils.changTheme(this, theme);
    }
}

参考:
https://github.com/lguipeng/Notes

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,009评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,808评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,891评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,283评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,285评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,409评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,809评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,487评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,680评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,499评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,548评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,268评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,815评论 3 304
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,872评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,102评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,683评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,253评论 2 341

推荐阅读更多精彩内容