Android 深色模式适配原理分析( 二 )

我们抽取其中的某些形状来动态改变颜色 , 例如我们抽取左右手臂以及机器小人身上的T恤
private fun setupValueCallbacks() {// 机器人右手臂val rightArm = KeyPath("RightArm", "Group 6", "Fill 1")// 机器人左手臂val leftArm = KeyPath("LeftArmWave", "LeftArm", "Group 6", "Fill 1")// 机器人T恤val shirt = KeyPath("Shirt", "Group 5", "Fill 1")// 设置右手臂颜色lottie_android_animate.addValueCallback(rightArm, LottieProperty.COLOR) {ContextCompat.getColor(this, R.color.color_main_1)}// 设置左手臂颜色lottie_android_animate.addValueCallback(shirt, LottieProperty.COLOR) {ContextCompat.getColor(this, R.color.color_light)}// 设置T恤颜色lottie_android_animate.addValueCallback(leftArm, LottieProperty.COLOR) {ContextCompat.getColor(this, R.color.color_custom)}// 播放动画描边颜色lottie_playing_animate.addValueCallback(KeyPath("**"), LottieProperty.STROKE_COLOR) {ContextCompat.getColor(this, R.color.color_text_0)}}由于color_main_1、color_light以及color_custom都已经定义过深色模式和明亮模式的色值 , 因此在深色模式切换时 , Lottie动画的这个机器小人的左右手臂和T恤颜色会随着深色模式切换而变化 。
同样的对于播放动画 , 我们也可以设置描边颜色 , 来达到深色模式切换的效果 。
网络获取图片
对于网络获取的图片 , 可以让服务接口分别给出明亮模式和深色模式两套素材 , 然后根据上述的深色模式判断来进行切换
Glide.with(this).load(if(isNightMode() nightImageUrl else imageUrl)).into(imgView)Force Dark
看到这里可能会有人有疑问 , 对于大型的项目而言 , 里面已经hardcore了很多的颜色值 , 并且很多图片都没有设计成深色模式的 , 那做深色模式适配是不是一个不可能完成的任务呢?答案是否定的 。 对于大型项目而言 , 除了对所有的颜色和图片定义night资源的自定义适配方法外 , 我们还可以对使用Light风格主题的页面进行进行强制深色模式转换 。
我们可以分别对主题和View设置强制深色模式 。 对于主题 , 在Light主题中设置android:forceDarkAllowed , 例如:
true对于View , 设置View.setForceDarkAllowed(boolean))或者xml来设置是否支持Force Dark , 默认值是true 。
这里需要注意的是 , Force Dark的设置有以下几个规则:

  1. 要强制深色模式生效必须开启硬件加速(默认开启)
  2. 主题设置的Force Dark仅对Light的主题有效 , 对非Light的主题不管是设置android:forceDarkAllowed为true或者设置View.setForceDarkAllowed(true)都是无效的 。
  3. 父节点设置了不支持Force Dark , 那么子节点再设置支持Force Dark无效 。 例如主题设置了android:forceDarkAllowed为false , 则View设置View.setForceDarkAllowed(true)无效 。 同样的 , 如果View本身设置了支持Force Dark , 但是其父layout设置了不支持 , 那么该View不会执行Force Dark
  4. 子节点设置不支持Force Dark不受父节点设置支持Force Dark影响 。 例如View设置了支持Force Dark , 但是其子Layout设置了不支持 , 那么子Layout也不会执行Force Dark 。
Tips:一个比较容易记的规则就是不支持Force Dark优先 , View 的 Force Dark设置一般会设置成 false , 用于排除某些已经适配了深色模式的 View 。