前言
对于资讯阅读类app的来说,夜间模式是必不可少的。本文提供一种不重启Activity实现动态切换主题的方案。
思路分析
基于接口回调机制,每个基类(BaseActivity)都实现同一个接口 ThemeChangeCallback
1 2 3
| interface ThemeChangeCallback { void onChangeTheme(); }
|
用一个列表保存ThemeChangeCallback
1
| private static List<ThemeChangeCallback> sCallbacks = new ArrayList<ThemeChangeCallback>();
|
当改变主题时,对每个ThemeChangeCallback调用onChangeTheme,然后在BaseActivity的onChangeTheme方法中实现背景或者资源的切换即可.
1 2 3 4 5
| public static synchronized void changeTheme() { for (ThemeChangeCallback callback : sCallbacks) if (callback != null) callback.onChangeTheme(); }
|
实现
BaseActitivy.java
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
| public class BaseActivity extends AppCompatActivity implements ThemeUtils.ThemeChangeCallback { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); ThemeUtils.addCallback(this); } @Override protected void onDestroy() { super.onDestroy(); ThemeUtils.removeCallback(this); } @Override public void onChangeTheme() { Drawable drawable = null; if (ThemeUtils.getCurrentThemeId() == ThemeUtils.DAY_THEME_ID) { drawable = getResources().getDrawable(R.color.colorPrimary); } else if (ThemeUtils.getCurrentThemeId() == ThemeUtils.NIGHT_THEME_ID) { drawable = getResources().getDrawable(R.color.colorAccent); } if (getWindow() != null) { getWindow().setBackgroundDrawable(drawable); } if (getSupportActionBar() != null) { getSupportActionBar().setBackgroundDrawable(drawable); } } }
|
MainActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class MainActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn = (Button) findViewById(R.id.btn_change_bg); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ThemeUtils.changeTheme(); } }); } }
|
ThemeUtils.java
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
| public class ThemeUtils { private static List<ThemeChangeCallback> sCallbacks = new ArrayList<ThemeChangeCallback>(); private static int sCurrentThemeId = 0 ; public static int DAY_THEME_ID = 0 ; public static int NIGHT_THEME_ID = 1 ; private ThemeUtils() {} public static void addCallback(ThemeChangeCallback callback) { if (callback != null) { sCallbacks.add(callback); } } public static void removeCallback(ThemeChangeCallback callback) { if (callback != null) { sCallbacks.remove(callback); } } public static synchronized void changeTheme() { sCurrentThemeId = sCurrentThemeId == DAY_THEME_ID ? NIGHT_THEME_ID : DAY_THEME_ID; for (ThemeChangeCallback callback : sCallbacks) if (callback != null) callback.onChangeTheme(); } public static int getCurrentThemeId() { return sCurrentThemeId; } interface ThemeChangeCallback { void onChangeTheme(); } }
|
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.netease.changetheme.MainActivity"> <Button android:id="@+id/btn_change_bg" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="change bg" android:layout_centerInParent="true"/> </RelativeLayout>
|
效果
缺陷
改变背景色时,沉浸式状态栏没有相应改变,有待优化。