不闪屏切换Android App主题
来源:互联网 发布:淘宝手机比京东便宜 编辑:程序博客网 时间:2024/05/17 04:35
最近想给自己的一个闹钟App增加一个夜间模式,一个比较简便的切换主题的方式就是在Styles.xml中设置两套Theme,分别是白天模式的主题Theme,还有一个是夜间模式的Theme。然后,通过在该Activity中的setContentView()方法之前,使用setTheme(...)方法设置Activity的Theme。但是重新设置的主题Theme必须调用recreate()方法使得Activity重新调用onCreate()方法才能表现出来。因此,这个时候会闪屏。我们先详细介绍下这种方式的实现,后面再说解决闪屏的方法。
第一步,确认哪些属性是需要根据主题变化而改变的
以下面这个活动为例,我希望在点击Change Theme按钮后,可以改变
- StatusBar的颜色
- ToolBar的颜色
- 整个Activity的背景颜色
- 以及“Hello Theme”这个TextView的背景颜色
在以上打算随着主题Theme修改的属性中,前三个属性是可以直接在Theme的style.xml文件中设置的,最后一个TextView的背景颜色是需要首先自定义一个属性,然后才能够在style.xml文件中设置的
第二步自定义属性
在values文件夹下,新建attrs.xml文件。下面的代码代表这新建一个名为"Text_bg_Color"的属性,该属性值是color类型或者reference引用类型。
<?xml versi encoding="utf-8"?> <resources> <attr name="Text_bg_Color" format="color|reference"/> </resources>
第三步定义不同的主题风格
在styles.xml中定义不同Theme,以便后面进行切换。下面分别定义了两个Theme的style。第一个是默认的主题,也就是白天模式。第二个是夜间模式。两个模式都是继承了"Theme.AppCompat.Light.NoActionBar",所以绝大多属性都是一样的,不同的是分别自定义了一些属性。
- colorPrimary是Toolbar的背景颜色
- colorPrimaryDark是StatusBar的颜色
- android:textColorPrimary是主标题的字体颜色
- android:colorControlNormal是控制元件的默认状态颜色以及overflow menu(三个点)的颜色
- colorAccent是控制元件在选中状态的颜色
android:windowBackground是Activity的背景颜色
<resources > <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar" > <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorLight</item> <item name="colorPrimaryDark">@color/colorLight</item> <item name="android:textColorPrimary">@android:color/black</item> <item name="android:colorControlNormal">@android:color/white</item> <item name="colorAccent">@color/colorAccent</item> <item name="android:windowBackground">@android:color/white</item> <item name="TextView_bg_Color">@android:color/white</item> </style> <style name="AppThemeNight" parent="Theme.AppCompat.Light.NoActionBar" > <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorNight</item> <item name="colorPrimaryDark">@color/colorNight</item> <item name="android:textColorPrimary">@android:color/black</item> <item name="android:colorControlNormal">@android:color/white</item> <item name="colorAccent">@color/colorAccent</item> <item name="android:windowBackground">@android:color/black</item> <item name="TextView_bg_Color">@color/colorGray</item> </style> </resources>
在布局文件中,TextView要使用对应style中的TextView_bg_Color属性。"?attr/TextView_bg_Color"代表使用自定义属性TextView_bg_Color的值,而该属性的已经呗Theme文件所定义。所以,TextView的背景颜色就被Theme所定义了。
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/Theme_Button" android:background="?attr/TextView_bg_Color" android:id="@+id/text_view" android:text="Hello Theme"/>
第四步在Activity中切换主题Theme
自定义一个ThemeUtile类,这是一个帮助切换主题的工具类。这个类提供了一个public static的布尔型的变量night,用来记录整个App所处于的主题模式。这个类还提供了一个public static方法changeTheme(),根据night的值,来对所有的Activity设置主题。
public class ThemeUtile { public static boolean night = false; public static void changeTheme(Activity activity){ if (ThemeUtile.night){ activity.setTheme(R.style.AppThemeNight); }else{ activity.setTheme(R.style.AppTheme); } }}
接着设置切换主题Button的点击事件。通过设置不同的night值,来设置不同的主题模式。因为setTheme()方法必须要在setContentView()方法之前调用,所以为了使当前Activity的主题切换成功,需要调用recreate()方法来重新调用onCreate()方法。这样也导致了当前Activity被销毁,并重新启动,所以会出现闪屏的现象。
Butt (Button) findViewById(R.id.Theme_Button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (ThemeUtile.night) { ThemeUtile.night = false; } else { ThemeUtile.night = true; } recreate(); } });
第五步 解决闪屏的问题
我搜索了很多解决不闪屏切换主题的方法,要么效果不太好,要么比较“难”,需要较深的知识积累,我就想了一个比较取巧的方法,但是没有那么优雅。由于在当前屏幕值重新设置主题,会导致重新调用onCreate()方法导致闪屏。我们可以在一个新开的Activity中通过ThemeUtile.night变量重新设置主题,但不调用recreate()方法切换主题,而是“手动”设置需要改变的属性,在退出该Activity时,使用Intent回到之前的界面,并 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
,使之前的Activity全部出栈,重新创建一个新的Activity,执行onCreate()方法,从而改变主题。
代码如下:
//在onCreate()方法中 ThemeUtile.changeTheme(this);setContentView(R.layout.second_activity); super.onCreate(savedInstanceState); ... //设置改变主题按钮的点击事件 button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (! ThemeUtile.night) { findViewById(R.id.sec_activity).setBackgroundColor(getResources().getColor(R.color.colorGray)); getWindow().setStatusBarColor(getResources().getColor(R.color.colorGray)); toolbar.setBackgroundColor(getResources().getColor(R.color.colorGray)); ThemeUtile.night = true; }else { findViewById(R.id.sec_activity).setBackgroundColor(getResources().getColor(R.color.colorWhite)); getWindow().setStatusBarColor(getResources().getColor(R.color.colorLight)); toolbar.setBackgroundColor(getResources().getColor(R.color.colorLight)); ThemeUtile.night = false; } } }); //重写onBackPressed()方法 @Override public void onBackPressed() { Intent intent = new Intent(SecondActivity.this,MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); super.onBackPressed(); }
就是这样,虽然不是很优雅,但是完成了不闪屏切换Android App主题。
注意,setTheme()
方法必须在setContentView()
和super.onCreate()
之前调用,否则,Theme中的某些属性将无法显示出来。
- 不闪屏切换Android App主题
- Android app主题切换
- Android 用户切换APP主题
- app 主题切换
- Android实现app主题动态切换的两种方式
- 关于android动态切换app主题颜色方案
- Android App切换主题的实现原理剖析
- Android 实现切换主题皮肤功能(类似于众多app中的 夜间模式,主题包等)
- Android 实现切换主题皮肤功能(类似于众多app中的 夜间模式,主题包等)
- Android 实现切换主题皮肤功能(类似于众多app中的 夜间模式,主题包等)
- Android 把项目从App主题切换到AppCompat主题所碰到的一些问题
- Android动态切换主题
- Android动态切换主题
- Android 应用主题切换
- Android主题切换方案
- Android动态切换主题
- Android动态切换主题
- android 切换主题
- Linux命令--grep
- Linux初学者必备命令
- poj1308 并查集
- Hadoop2.0的HA介绍
- 有关Perference的学习
- 不闪屏切换Android App主题
- 如何向非技术人员解释“稀疏傅里叶变换”算法?
- HDU 1009 FatMouse' Trade (贪心)
- 电脑蓝屏解决方案:[1]错误代码0x0000000A
- 学习决策树算法
- 七牛云直播-Android端播放卡顿问题处理
- inno setup 打包相关技术要点
- ubuntu引导问题
- iOS 第三方框架管理cocoapods 关于Mac 10.11 系统升级无法使用的问题