前言
Android 10系統增加了暗黑模式,但是並沒有像IOS那樣強制適配。暗黑模式下可大幅減少耗電量。而且在晚上使用手機的情況下可以有效的保護視力,減少對眼睛的傷害。這個可以在手機的“設置->顯示和亮度->深色模式”進行切換。(以華爲手機爲例)
暗黑模式一般由兩種適配方法,下面我們就一起來了解Android 10系統的暗黑模式的兩種適配方法。(注意:這裏前提是要把項目的targetSdkVersion 設置爲29 )
手動適配
手動適配相對來說比較簡單,就是類似於之前的屏幕適配。比如適配顏色的話,就在res 下新建 values-night目錄,創建對應的colors.xml文件。如果適配圖片的話,就創建對應的 drawable-night目錄。
下面我們就一起來嘗試一下:
寫一個佈局,裏面有圖片和文字:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ImageView
android:id="@+id/iv_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:src="@drawable/icon_pause"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="文字顏色"
android:textColor="@color/color_content"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/iv_image" />
<TextView
android:id="@+id/tv_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/bt_paly"
android:layout_width="200dp"
android:layout_height="50dp"
android:layout_marginTop="20dp"
android:text="播放"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_text" />
<Button
android:id="@+id/bt_pause"
android:layout_width="200dp"
android:layout_height="50dp"
android:layout_marginTop="20dp"
android:text="暫停"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/bt_paly" />
</androidx.constraintlayout.widget.ConstraintLayout>
針對適配圖片:在res文件夾下創建了兩個文件夾,drawable-xhdpi用於放置白天模式下的圖片,和drawable-night-xhdpi用於放置黑夜模式下的圖片。
針對適配文字顏色:在values下有一個colors.xml文件用於書寫白天模式下的顏色值,在res文件夾下創建一個values-night文件夾,裏面同樣創建一個colors.xml文件,用於書寫黑夜模式下的顏色值。
我們現在設置白天模式下圖片加載:
顏色值設置:
<color name="color_content">#FF0000</color>
黑夜模式設置圖片加載:
顏色值設置:
<color name="color_content">#FFFFFF</color>
運行之後,看一下效果:
好了,手動適配的方式就介紹到這裏,手動適配其實說白了就是資源適配。
自動適配
Android10 提供了一種自動適配的方式,即Fork Dark。應用可以通過設置 android:forceDarkAllowed=“true”,來實現暗黑模式的自動適配。
注意:如果使用Dark Theme主題(例如Theme.Material),則系統不會應用 Force Dark。同樣,如果應用的主題繼承自 DayNight 主題(例如Theme.AppCompat.DayNight),則系統不會應用 Force Dark。
如果使用的是 DayNight 或 Dark Theme 主題,則設置forceDarkAllowed 不生效。
此外還可以通過setForceDarkAllowed(boolean) 在特定的View上控制 Force Dark。
例:在res文件夾下,新建一個values-29的文件夾,裏面新建一個styles.xml的文件,裏面寫上在暗黑模式下要設置的Theme。
這時候,在系統設置裏面,把系統切換爲暗黑模式,那麼當前App就會使用values-29文件夾下的styles.xml文件裏面的AppTheme主題。但是這裏要注意的是,因爲主題是:
parent="Theme.AppCompat.DayNight.DarkActionBar"
所以,這裏的
<item name="android:forceDarkAllowed">false</item>
不管設置爲true或者false,forceDarkAllowed都不會生效。
如果主題設置的是:
parent="Theme.AppCompat.Light.DarkActionBar"
那麼當forceDarkAllowed爲false的時候,顯示白天模式,當forceDarkAllowed爲true的時候,顯示暗黑模式。此時,forceDarkAllowed的設置是生效的。
<item name="android:forceDarkAllowed">false</item>
<item name="android:forceDarkAllowed">true</item>
手動切換主題
此外,我們還可以通過 AppCompatDelegate.setDefaultNightMode(@NightMode int mode)方法手動切換主題:
public static class ThemeHelper {
public static final String LIGHT_MODE = "light";
public static final String DARK_MODE = "dark";
public static final String DEFAULT_MODE = "default";
public static void applyTheme(@NonNull String themePref) {
switch (themePref) {
case LIGHT_MODE: {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
break;
}
case DARK_MODE: {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
break;
}
default: {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY);
}
break;
}
}
}
}
參數mode有以下幾種模式:
淺色 - MODE_NIGHT_NO
深色 - MODE_NIGHT_YES
由省電模式設置 - MODE_NIGHT_AUTO_BATTERY
系統默認 - MODE_NIGHT_FOLLOW_SYSTEM
監聽深色主題是否開啓
我們還可以監聽到暗黑的主題是否開啓
(1)在清單文件中給對應的Activity配置 android:configChanges=“uiMode”:
<activity android:name=".MainActivity"
android:configChanges="uiMode">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
(2)在onConfigurationChanged方法中獲取:
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
int currentNightMode = newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK;
switch (currentNightMode) {
case Configuration.UI_MODE_NIGHT_NO:
Log.e("=======","=====關閉夜間模式====");
// 關閉
break;
case Configuration.UI_MODE_NIGHT_YES:
Log.e("=======","=====開啓夜間模式====");
// 開啓
break;
default:
break;
}
}
這時,可以通過系統的設置切換暗黑模式的關閉和開啓,查看下輸出的Log。
判斷深色主題是否開啓
我們還可以判斷深色模式是否開啓:
public static boolean isNightMode(Context context) {
int currentNightMode = context.getResources().getConfiguration().uiMode &
Configuration.UI_MODE_NIGHT_MASK;
return currentNightMode == Configuration.UI_MODE_NIGHT_YES;
}
結語
Android 10新加了暗黑模式,我們可以通過Force Dark來自動適配,然後再通過手動適配來進行圖片資源以及顏色等的適配。