博主声明:
转载请在开头附加本文链接及作者信息,并标记为转载。本文由博主 威威喵 原创,请多支持与指教。
在现在的很多应用中,都有一个夜间模式,由于大部分人玩手机都到深更半夜,白色的主题在夜晚不开灯的情况下,显得屏幕非常亮。一种办法是降低屏幕的亮度,就比如我的手机一般都开起了自动亮度的功能;还有一种办法就是将 App 切换到夜间模式,其实就是改变一下主题颜色。
在 Android support v7 包版本 23 及以后,系统就提供了一种简单而快速的方式,让我们得以很快的切换到夜间模式。接下来,通过一个案例来实现一下。
首先呢,我们建立一个空项目即可,但需要加入两个 package,如下:
相对应的,必须命名为 drawable-night 和 values-night
我们项目默认的主题颜色,也就是日间模式,如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#008577</color>
<color name="colorPrimaryDark">#00574B</color>
<color name="colorAccent">#D81B60</color>
<color name="colorCommonText">#5CACEE</color>
<color name="colorPressedBtnBg">#FF00FF</color>
<color name="colorCommonBtnBg">#CFCFCF</color>
</resources>
夜间模式,颜色需要换成黑色或深色,比较护眼吧
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#4F4F4F</color>
<color name="colorPrimaryDark">#363636</color>
<color name="colorAccent">#828282</color>
<color name="colorCommonText">#66FF99</color>
<color name="colorPressedBtnBg">#00FFFF</color>
<color name="colorCommonBtnBg">#708090</color>
</resources>
以上是 values package 的日间 / 夜间模式的适配,如果在 View 中还有引用到 drawable package 的话,也要做对应的处理。例如,给一个 Button 换样式,日间模式的样式代码如下:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/colorPressedBtnBg" android:state_pressed="true" />
<item android:drawable="@color/colorCommonBtnBg" android:state_pressed="false" />
</selector>
夜间模式,同样需要
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/colorPressedBtnBg" android:state_pressed="true" />
<item android:drawable="@color/colorCommonBtnBg" android:state_pressed="false" />
</selector>
到此,差不多就完成了一半。
接下来,就是使用代码去控制日间和夜间两种模式的切换效果了。一般的,这个切换行为是一个 Switch 开关,它的用法其实就和 CheckBox 一样,设置选中状态的变化监听即可。以下是 MainActivity 里的代码:
public class MainActivity extends AppCompatActivity {
private SharedPreferences mSharedPreferences;
private Switch sw_night_mode;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
sw_night_mode = (Switch) findViewById(R.id.sw_night_mode);
mSharedPreferences = getSharedPreferences("app_night_mode", MODE_PRIVATE);
boolean isNightMode = mSharedPreferences.getBoolean("night_mode", false);
if (isNightMode) {
sw_night_mode.setChecked(true);
} else {
sw_night_mode.setChecked(false);
}
sw_night_mode.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked && !isNightMode) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
mSharedPreferences.edit().putBoolean("night_mode", true).apply();
} else if (!isChecked && isNightMode) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
mSharedPreferences.edit().putBoolean("night_mode", false).apply();
}
startActivity(new Intent(MainActivity.this, MainActivity.class));
overridePendingTransition(R.anim.night_mode_open_anim, R.anim.night_mode_close_anim);
finish();
}
});
}
}
这里需要注意的一个点:因为我们在切换模式之后,需要先关闭当前 Activity,然后启动它。这个过程需要保存一下 Switch 被选中的状态,否则每一次打开 Activity 的时候,都默认没有被选中,就会造成切换不回来日间模式的问题。
还有一个问题,就是 Activity finish 了,然后在 start 会有一点生硬,这个可以用过渡动画来解决,一个是打开 Activity 动画:
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:fromAlpha="0"
android:interpolator="@android:anim/accelerate_interpolator"
android:toAlpha="1.0" />
关闭 Activity 的动画:
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:fromAlpha="1.0"
android:interpolator="@android:anim/accelerate_interpolator"
android:toAlpha="0" />
这里也需要注意一点,overridePedingTransition() 方法需要在 startActivity 之后调用,否则动画没有效果。
最后,来看看效果吧
到此为止,就搞定了一个简单快速夜间模式切换了。
如果需要保存当前的夜间模式,上面的操作是无法进行保存的,如果 App 被杀死的话,下次再进入则还是日间模式。所以,在 Activity 的 onCreate 方法之前,就应该去判断一下当前的模式,代码如下:
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
mSharedPreferences = getSharedPreferences("app_night_mode", Context.MODE_PRIVATE);
if (mSharedPreferences.getBoolean("night_mode", false)) {
getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_YES);
} else {
getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_NO);
}
super.onCreate(savedInstanceState);
}
这样的话,就会还原用户上一次保存的模式了。