博主聲明:
轉載請在開頭附加本文鏈接及作者信息,並標記爲轉載。本文由博主 威威喵 原創,請多支持與指教。
在現在的很多應用中,都有一個夜間模式,由於大部分人玩手機都到深更半夜,白色的主題在夜晚不開燈的情況下,顯得屏幕非常亮。一種辦法是降低屏幕的亮度,就比如我的手機一般都開起了自動亮度的功能;還有一種辦法就是將 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);
}
這樣的話,就會還原用戶上一次保存的模式了。