在Android开发中,实现切换夜间模式有通常有三种方案:
- 1、通过切换theme实现
- 2、通过resource id映射实现
- 3、通过Android Support Library的实现
其中第三种实现方案最简单,这里主要对其进行探讨,实现方式如下:
1. application中初始化
oncreate方法中初始化
private void initNightMode() {
boolean isNightMode = dataManager.isOpenNightMode();
AppCompatDelegate.setDefaultNightMode(isNightMode ? AppCompatDelegate.MODE_NIGHT_YES : AppCompatDelegate.MODE_NIGHT_NO);
}
2. 创建夜间模式资源目录
根据drawable,drawable-night,values,values-night文件夹,识别夜间模式和日间模式,values-night文件将爱创建colors.xml文件,里面写入夜间模式的颜色值,命名和正常模式相同,drawable以此类推。
3. 切换夜间主题
使用使用 Android Support Library 中的 UiMode 方法切换主题。要注意的是,这里的 Mode 有四种类型可以选择:
- MODE_NIGHT_NO:使用亮色(light)主题,不使用夜间模式;
- MODE_NIGHT_YES:使用暗色(dark)主题,使用夜间模式;
- MODE_NIGHT_AUTO:根据当前时间自动切换 亮色(light)/暗色(dark)主题;
- MODE_NIGHT_FOLLOW_SYSTEM(默认选项):设置为跟随系统,通常为 MODE_NIGHT_NO
当用户点击按钮切换日/夜间时,重新去设置相应的 Mode :
private void switchNight() {
int mode = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
if (mode == Configuration.UI_MODE_NIGHT_YES) { //白天模式
SharePrefUtil.getInstance().setNightModel(false);
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
} else {
SharePrefUtil.getInstance().setNightModel(true);
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
}
//方法1,会有问题
//recreate();
//方法2,重新启动MainActivity
Intent newIntent = new Intent(this, MainActivity.class);
newIntent.putExtra(Constant.NIGHT_MODEL, "2");
startActivity(newIntent);
finish();
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
}
由于调用recreate()方法会出现一些问题,这里采用第二种方法,重新启动当前activity,设置一个页面退出动画的效果,如果不是在首页中切换主题的,你也可以发送一个广播,首页中收到广播,重新启动当前页面。
至此,所有代码编写完毕。但在运行中发现一个问题,APP第一次安装运行的时候,view报空指针,程序崩溃,继承AppCompatActivity的activity会创建两次,查资料发现,用户模式变化会和切换横竖屏一样,activity重走生命周期,可以在清单文件中对activity配置android:configChanges="orientation|screenSize|uiMode" 属性,完美解决。