Android夜间模式 - DayNight Mode的使用

以前怎么实现的?

一般是搞多套资源切换呗。
我之前在我自己的App斧头便签实现夜间模式的方法是使用Prism框架。

// 主题切换框架
// https://github.com/StylingAndroid/Prism
// https://blog.leancloud.cn/3612/
compile 'com.stylingandroid.prism:prism:1.0.1'

使用方法上面的注释可以找到资料,大概是创建Prism对象,然后要在每个界面把要改变颜色的View都add进去。然后图标是动态set的。

新的实现方式

Android现在有官方的夜间模式方案,Support包从23.2版本开始支持夜间模式,也就是DayNight Mode。
已经出来一段时间了,所以网上关于DayNight使用方法其实很多。但是内容都不全面,大概内容就是说出下面这个大概的使用方法。

使用方法:

  • 继承AppCompatActivity
  • 使用Theme.AppCompat.DayNight这个Theme,例如如果你之前的祖宗
    Theme
Theme.AppCompat.NoActionBar

改为

Theme.AppCompat.DayNight.NoActionBar
  • 在Application中设置初始化一下Theme。
    例如像这样:
static {
        AppCompatDelegate.setDefaultNightMode(
                AppCompatDelegate.MODE_NIGHT_AUTO);
 }
  • 然后改变Theme的方法就是
getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_YES);
recreate(); // 这个是刷新,不然不起作用
  • 有四个模式可以选
MODE_NIGHT_NO // 日间模式,使用light theme
MODE_NIGHT_YES // 夜间模式,使用dark theme
MODE_NIGHT_AUTO // 根据系统时间自动切换
MODE_NIGHT_FOLLOW_SYSTEM // 跟随系统设置,这个是默认的

over,大致使用方法就是以上这样,你可以尝试新建一个新app改一下上述这几点就可以看到效果了。网上一些文章也就到此为止了。

具体问题

但是其实问题还有很多,例如这是一个很常见的app的界面。


Android夜间模式 - DayNight Mode的使用_第1张图片

那么问题来了:

  • 怎么设置切换时的具体颜色?
  • Toolbar怎么设置?
  • 悬浮按钮FloatingActionButton怎么设置?
  • 侧滑菜单NavigationView怎么设置?
  • 图标怎么设置?
  • RecycleView的每个item怎么设置?
  • alertdialog怎么设置?

这些问题的答案其实是同一个解,资源细分,values细分出values-night,drawable细分出drawable-night。这个和根据Android版本细分的values-v21是一个道理。

资源细分

具体怎么用呢?Material Design有一张经典的颜色设置指导图:


Android夜间模式 - DayNight Mode的使用_第2张图片

所以你会在colors.xml设置好一些颜色,然后在styles.xml这样设置:


那就创建一个新的values-night把再新建一个styles.xml,把夜间模式的颜色在这里设置下。这样再切换到夜间模式时就会使用values-night的资源。你不用把整个styles.xml的内容都复制过来,例如你只想改colorPrimary,你就设置一个colorPrimary就行了。


Android夜间模式 - DayNight Mode的使用_第3张图片

当然了,不只是styles.xml,colors.xml,dimens.xml,strings.xml都可以这么做。意思这些资源调用都是就近原则,切换到夜间模式时values-night有就使用values-night的,没有还是使用values的。

比如说我要改侧滑菜单NavigationView头部的颜色,官方的实现方法就是这样吧:


然后你找到了nav_header_main,点进去发现背景颜色是 android:background="@drawable/side_nav_bar"


    

那就按我上面说的,新建一个drawable-night,然后取一个名字一模一样的资源文件side_nav_bar。
然后我改下颜色:


    

图标也是一个道理,建drawable-night-hdpi,drawable-night-xhdpi什么的,把图标放进去,记得取一样的名字。
看一下效果(颜色暂时随便设置的,有点丑):


Android夜间模式 - DayNight Mode的使用_第4张图片

所以关键是资源细分,这样你就可以解决我上面提的这些问题。
还有个对话框,对话框自然也是有DayNight的Theme的。
在styles.xml加一个theme