对于一款阅读类的软件,夜间模式是不可缺少的。最初看到这个需求时候觉得无从下手,没有一点头绪。后来通过查阅资料发现Android官方在Support Library 23.2.0中已经加入了夜间主题。也就是只需要通过更换主题便可实现日间模式和夜间模式的切换。下面截取项目实现的夜间模式效果图:
三 、实现夜间模式时遇到的问题及解决方案
利用谷歌官方提供的这个方案实现夜间模式的过程中遇到了不少的问题。且 上资料较少,大多文章讲解仅仅以一个简单的demo为例。但在用到实际项目中时会遇到很多的麻烦。这里主要总结了笔者曾经遇到过的难以解决的几个问题。
1.白天/夜间模式切换时闪屏问题
上一节中已经提到了在调用recreate()方法时会有闪屏问题。其实闪屏问题的解决比较简单。我们大可以不掉用recreate()方法,而是自己重启当前activity并为activity设置启动和退出动画即可!实现代码如下:
如上代码,我们自行调用startActivity启动了设置页面并为其添加了一个透明渐变的启动动画。最后调用finish结束掉旧的设置页面。这样闪屏问题便迎刃而解。模式切换也变得流畅自然。
2.切换夜间模式后返回MainActivity,MainActivity页面没有更新。解决这个问题可以在切换模式后从设置页面发送一个广播,然后在MainActivity中接收到这个广播后重启MainActivity即可。根据官方的推荐更换夜间模式后需要调用recreate()方法刷新页面。但是recreate()方法巨坑无比,调用recreate()方法引起了诸多问题。详见问题3、4、5。因此解决这个问题笔者并没有在MainActivity调用中调用recreate()方法。而是在SettingActivity中定义了一个boolean值来标记是否切换了夜间模式。然后重写了onKeyDown()方法。如果切换了夜间模式则在返回时发出一个广播结束掉MainActivity,然后调用startActivity()重启了MainActivity并添加了启动动画,让用户感觉是只是返回了主页面。其实思想跟解决问题1有些类似。还是结合代码来看吧。
SettingActivity中的代码
MainActivity中的代码:
最后还有点问题需要说明,由问题1我们可以知道,改变模式后,我们重启了SettingActivity。因此在该类中定义的一个标记是否切换了夜间模式的boolean值并不能起到作用。解决办法是将这个值保存到SharedPreference中。然后重启SettingActivity后再取出该值。可以看代码,这点真心有点绕啊。。。
注意问题1中的setNightMode()方法中有一句代码 UserInfoTools.setChangeNightMode(this,true);将改变了夜间模式设置为了true并保存到了SharedPreferences中,然后在onCreate()中有以下代码来初始化isChangeNightMode的值。
3.设置白天/夜间模式后出现无故闪退问题
这个问题说来比较奇怪,原因是切换了夜间模式后在MainActivity中调用了recreate()方法。具体原因笔者也没有弄清楚,调试了好一阵子也没有找出个所以然来。后来果断放弃了在MainActivity中调用recreate()方法,而是换成了startActivity()重新启动了MainActivity。之后这个问题便不复存在了。
4.点击ToggleButton切换模式后应用黑屏,随后挂掉。这个问题的最终原因还是因为recreate()方法引起的。如果你用了ToggleButton切换白天/夜间模式,并且为ToggleButton设置了setOnCheckChangedListener()方法,那么你将有很大概率碰到这个问题。引起这个问题的原因是因为调用了recreate()方法后Activity重新启动,但是新启动的Activity保存了之前Activity的状态。因此在重启时候重新设置了TouggleButton,继而调用了又setOnCheckChangedListener()方法,结果悲剧了。。。一个死循环产生了,程序不黑屏才怪。因此最简单的办法是放弃recreate()方法,改用问题1中的方法!(其实细心的小伙伴应该已经发现了,我的代码中仅仅是为ToggleButton设置了setOnClickListener()…机智如我啊)如果你有强迫症必须要使用setOnCheckChangedListener和recreate()方法那么也不是没有解决方案。可以定义一个boolean成员变量,然后在onCreate()方法中判断savedInstanceState是否为null,然后给这个boolean成员变量赋值,并在setOnCheckChangedListener()方法中根据这个boolean成员变量的值去调用设置夜间模式的方法即可。
5.设置夜间模式后MainActivity调用recreate()方法,MainActivity中的”发现“页面没有加载出来。发现页面如下面图片所示,也就是一个Fragment中嵌套了一个ViewPager。调用recreate()后整个ViewPager消失了。。。没有加载出来!!!

解决方案,放弃使用recreate(),改用问题1中的方法!
万恶的recreate()方法!难道是我使用的姿势不对/p>
开源库推荐
BannerViewPager
一个基于ViewPager2实现的具有强大功能的无限轮播库。支持多种页面切换效果和指示器样式。
ViewPagerIndicator
一个适用于ViewPager和ViewPager2的指示器,支持多种滑块样式及滑动模式
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!