日/夜模式切换作为一个App的基本功能经常会被使用到,接下来就举出一些常用的日/夜模式切换的方法

使用UIMode的方法
这种方式操作起来比较简单,就是将不同模式下的资源分开存放,然后调用方法切换资源即可

  • 资源存放的路径
  • 切换资源的方法

其中AppCompatDelegate.MODE_NIGHT_YES代表切换到夜间模式,AppCompatDelegate.MODE_NIGHT_NO代表切换到日间模式
如果是在新的Activity中切换日/夜模式则需要用RxBus(关于RxBus的用法可以参照我上篇博客)通知在后台的Activity调用recreate()重启Activity

  • 最终效果
  • 存在问题

由于需要recreate(),会重绘Activity导致屏幕闪烁,重新加载Avtivity时需要注意Activity内元素的保存

使用Theme
通过切换不同的主题来实现切换日/夜模式的效果

  • 在attrs.xml中设置主题中需要替换资源
  • 设置日/夜模式主题
  • 在layout文件中使用arrts中的资源属性
  • 在Activity中切换主题

设置主题需要放在setContentView()之前,所以每次切换完日/夜模式后都需要重新加载Activity

  • 存在问题

与UIMode方法相同由于需要recreate(),会重绘Activity导致屏幕闪烁,并且在有比较多的属性需要修改时会导致style比较复杂

为了决解改变日/夜模式后屏幕闪烁的问题,我看了不少博客,终于找到了一个比较符合要求的项目,能够实现uiMode方法的不重建Activity切换日/夜模式。
项目地址:https://github.com/geminiwen/SkinSprite

效果:

具体思路是在Activity创建View的过程中注入自己的代码。
接下来分析一下这个lib的具体代码

  • 首先是SkinnableActivity,继承自AppCompatActivity,在这个Activity中对View的创建进行拦截,我们主要关注三个方法

1)

注入自己的LayoutInflatorFactory,使inflate在这个LayoutInflaterFactory中执行

2)

这是具体需要创建View的方法,可以看到他将具体的创建逻辑放到了SkinnableViewInflater中,这个类之后在做分析

3)

这是一个我们之后需要切换日夜模式需要调用的方法,其中主要调用逻辑有

对系统日/夜模式的资源进行切换

如果api等级大于等于21(即5.0及以上版本)则更换状态栏和标题栏资源

对于内容中的日/夜资源进行切换,这个方法我们可以看下他的具体实现

可以看到这是一个递归的方法,功能是遍历了view下所有的子view,对实现了Skinnable接口并 大专栏  日/夜模式切换且isSkinnable()返回true的view调用applyDayNight()。可以猜想到这些View就是自定义的View,这个applyDayNight()就是刷新View中资源的方法。

  • 接下来可以看下上面的SkinnableViewInflater这个类

这个是SkinnableViewInflater中最主要的方法,根据name创建出不同的View,即自定义的View,这里并没有把所有的view都做出来,但是都大同小异,如果不够用还可以自己添加

  • 最后只剩下View的没有看了,由于View比较多而且其中的内容都相似,我们拿SkinnableLinearLayout作为案例进行研究

SkinnableLinearLayout中的思路也比较简单,在构造方法中向mAttrsHelper添加如属性,在需要刷新是再从mAttrsHelper中取出。对于不同的View也只是属性的内容不同而已

至此就是这个项目的大致源码,然后只需要将Activity继承SkinnableActivity,将uiMode中的
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
改为
setDayNightMode(AppCompatDelegate.MODE_NIGHT_YES);
并且不需要调用recreate()方法。需要注意的是还需要在该Activity中添加上android:configChanges=”uiMode”。

结语:这是我第一次写关于阅读源码的博客,尽管选了一个比较简单的lib但还是表达得比较凌乱。我之后还是会多多尝试写这方面的博客,努力提高自己的水平。

参考博客:
android 实现【夜晚模式】的另外一种思路
Android通过改变主题实现夜间模式
Android实现日夜间模式的深入理解

01-05 00:23
查看更多