原文链接:https://lingyunzhu.github.io/2016/03/07/Android动态设置主题(使用RxBus模式)/
一、定义主题颜色
color.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | <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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | <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> |
三、在需要的地方弹出主题选择对话框
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 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,其他主题颜色类似
1 2 3 4 | <?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 |
四、主题选择框中颜色适配器及其xml
主题选择框中颜色适配器ColorsListAdapter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <?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发布事件和处理事件
发布
1 2 3 | private void changeTheme(MyThemeUtils.Theme theme) { RxBus.getInstance().post(new RxbusEvent(theme)); } |
接收
1 2 3 4 5 6 7 | rxSbscription=RxBus.getInstance().toObserverable(RxbusEvent.class) .subscribe(new Action1<RxbusEvent>() { @Override public void call(RxbusEvent rxbusEvent) { changeTheme(rxbusEvent.getTheme()); } }); |
六、用到的工具类
PreferenceUtils
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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