android 夜间模式浅析

3,125 阅读3分钟
原文链接: flyou.ren

几种实现夜间模式的方式

1:修改theme,重启activity

使用时定义不同的主题,通过切换主题重启acticity的方式完成切换

优点:正儿八经的夜间模式,配色看着舒服

缺点:图片刺眼、闪屏

2:覆盖一定透明度的View

使用一个带黑色带透明度的View,盖在现有的activity上,效果类似你带上墨镜,看着太阳不刺眼。

优点:不用重启activity,不闪屏;加上透明度过渡动画,模式之间切换非常舒服,解决了1中,白底图片依旧刺眼的问题。

缺点:配色没变化,就算带上墨镜,白天依旧是白天。

3:使用动态换肤方案

一般借助于第三方库完成换肤,如:
github.com/hongyangAnd…
github.com/fengjundev/…

优点:不用重启activity,不闪屏;可以为程序提供多种皮肤方案不局限于夜间/白天模式。

缺点:在制作方面代价过大,侵入性较强,需要以来第三方库完成,可靠性不能得到保证。

4:使用 Support Library 23.2.0 DayNight主题实现

优点:Google自家产品,可靠性高,配置简单,省心省力,在仅仅需要实现夜间/日间模式的应用内强烈推荐。

缺点:不支持多皮肤切换算吗?貌似今天只谈夜间模式的实现……。

使用DayNight主题来实现夜间模式

对于前两种方式来说,从实现来说是不困难的但是对用户的体验在一定程度上是很不好的,一个需要重启activity,一个配色无法改变都是我们不推荐的。

当然第三种方式市面上也有比较成熟的第三方库来完成程序的换肤,但是对于单单需要夜间模式的应用来说未免有些大材小用了。

今天我们使用DayNight主题来实现换肤功能。

1.定义DayNight主题,及相关属性


      <!-- Customize your theme here. -->
      <item name="colorPrimary">@color/colorPrimary</item>
      <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
      <item name="colorAccent">@color/colorAccent</item>
 		

可以在主题中定义一些颜色尺寸等属性,在vlaues的colors.xml 声明color属性。



   #3F51B5
   #303F9F
   #FF4081

在res下面创建values-night文件夹,创建colors.xml声明color属性



   #1f2023
   #18181a
   #FF4081

2.为程序设置初始模式

程序中进行主题的初始化。你需要调用 AppCompatDelegate.setDefaultNightMode() ,它有四个参数:

MODE_NIGHT_NO. 使用亮色(light)主题

MODE_NIGHT_YES. 使用暗色(dark)主题

MODE_NIGHT_AUTO. 根据当前时间自动切换 亮色(light)/暗色(dark)主题

MODE_NIGHT_FOLLOW_SYSTEM(默认选项). 设置为跟随系统,通常为 MODE_NIGHT_NO

如在Application中进行初始化:

public class MyApplication extends Application {
static {
    AppCompatDelegate.setDefaultNightMode(
            AppCompatDelegate.MODE_NIGHT_NO);
}

@Override
public void onCreate() {
    super.onCreate();
}

}

3.在初始化时就切换夜间模式

 public class MyActivity extends AppCompatActivity {
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (savedInstanceState == null) {
        // Set the local night mode to some value
        getDelegate().setLocalNightMode(
                AppCompatDelegate.MODE_NIGHT_...);
        // 调用 recreate() 使设置生效
        recreate();
    }
} }

4.如何获取当前主题的状态

int currentNightMode = getResources().getConfiguration().uiMode
    & Configuration.UI_MODE_NIGHT_MASK;

case Configuration.UI_MODE_NIGHT_NO:

case Configuration.UI_MODE_NIGHT_YES:

case Configuration.UI_MODE_NIGHT_UNDEFINED:

可以通过上面面的几种状态来进行相应的操作如:
```
private void judeStatusOfDayNight() {

    int currentNightMode = getResources().getConfiguration().uiMode
            & Configuration.UI_MODE_NIGHT_MASK;
    switch (currentNightMode) {
        case Configuration.UI_MODE_NIGHT_NO:
            getDelegate().setDefaultNightMode(
                    AppCompatDelegate.MODE_NIGHT_YES);


            break;
        case Configuration.UI_MODE_NIGHT_YES:
             getDelegate().setDefaultNightMode(
                AppCompatDelegate.MODE_NIGHT_NO);
            break;
        case Configuration.UI_MODE_NIGHT_UNDEFINED:
            getDelegate().setDefaultNightMode(
                    AppCompatDelegate.MODE_NIGHT_AUTO);
            break;
    }
    // 调用 recreate() 使设置生效
    recreate();
}

效果如下:

后记

当然,这仅仅是一个简单的例子,如果涉及图片你需要创建drawable-night文件夹。

对于一些按钮的颜色背景都需要做相应的处理,当然处理起来还是很简单的。

那么现在为你的程序加上夜间模式吧。