深色主題

深色主題適用於 Android 10 (API 級別 29) 及以上版本。此功能有眾多優點:

  • 可大幅減少耗電量 (視裝置的螢幕技術而定)。
  • 可改善低視能及對明亮光線敏感使用者的可視性。
  • 能讓所有人在低光源環境中輕鬆使用裝置。

深色主題適用於 Android 系統 UI,以及在裝置上執行的應用程式。

如要在 Android 10 (API 級別 29) 及以上版本啟用深色主題,有以下三種方式:

  • 使用系統設定 (「設定」->「顯示」->「主題」) 啟用深色主題。
  • 使用快速設定方塊從通知匣中切換主題 (啟用後)。
  • 如果使用 Pixel 裝置,選擇「省電模式」時會同時啟用深色主題。其他原始設備製造商 (OEM) 不一定支援這項功能。

如要瞭解如何使用 WebView 元件將深色主題套用至網路內容,請參閱「在 WebView 中調暗網頁內容」。

在應用程式中支援深色主題

如要支援深色主題,必須將應用程式的主題 (通常位於 res/values/styles.xml 中) 設為沿用 DayNight 主題:

<style name="AppTheme" parent="Theme.AppCompat.DayNight">

您還可以使用 MaterialComponents 的深色主題

<style name="AppTheme" parent="Theme.MaterialComponents.DayNight">

這會將應用程式的主要主題對應到系統控制的夜間模式旗標,並賦予應用程式預設的深色主題 (如啟用)。

主題與樣式

主題與樣式應避免透過硬式編碼設定適用於淺色主題的色彩或圖示。請改用主題屬性 (建議做法) 或夜間適用的資源。

以下是兩個最重要的主題屬性:

  • ?android:attr/textColorPrimary 這是一般用途文字顏色。在淺色主題中接近黑色,在深色主題中則接近白色。具有停用狀態。
  • ?attr/colorControlNormal 一般用途圖示顏色。具有停用狀態。

建議使用質感設計元件,因為其顏色主題設定系統 (如主題屬性 ?attr/colorSurface?attr/colorOnSurface) 可讓您輕鬆使用適當的顏色。當然,您可以在主題中自訂這些屬性。

變更應用程式內主題

您可能想要讓使用者在應用程式執行期間變更應用程式主題。應用程式可讓使用者切換主題。建議選項如下:

  • 淺色
  • 深色
  • 系統預設 (建議的預設選項)

每個選項都會直接對應至其中一種 AppCompat.DayNight 模式:

如要切換主題,請呼叫 AppCompatDelegate.setDefaultNightMode()

強制使用深色模式

Android 10 提供「強制使用深色模式」功能,開發人員不用明確設定上述 DayNight 主題,即可快速實作深色主題。

「強制使用深色模式」會分析淺色主題應用程式的每個檢視畫面,並在繪圖至螢幕之前自動套用深色主題。有些開發人員會將「強制使用深色模式」與原生實作相結合,藉此縮短實作深色主題所需的時間。

應用程式必須在活動主題中設定 android:forceDarkAllowed="true",以選擇啟用「強制使用深色模式」。這個屬性會在所有系統和 AndroidX 提供的淺色主題上設定,如 Theme.Material.Light。使用「強制使用深色模式」時,請務必對應用程式進行全面測試,並視需要排除檢視畫面。

如果您的應用程式使用深色主題 (如 Theme.Material),系統不會套用「強制使用深色模式」。同樣,如果應用程式的主題沿用 DayNight 主題,由於自動主題切換功能,系統不會套用「強制使用深色模式」。

在檢視畫面上停用「強制使用深色模式」

可以使用 android:forceDarkAllowed 版面配置屬性或 setForceDarkAllowed(),來控管特定檢視畫面上的「強制使用深色模式」設定。

網頁內容

如要瞭解如何在網路內容中使用深色主題,請參閱「在 WebView 中調暗網頁內容」。如需套用深色主題的範例,請參閱 GitHub 上的 WebView 示範

最佳做法

下列各節說明實作深色主題的最佳做法。

通知與小工具

對於您在裝置上顯示但未直接控制的 UI 途徑,請務必確認您使用的任何檢視畫面都能反映主機應用程式的主題。通知和啟動器小工具就是兩個很好的例子。

通知

使用系統提供的通知範本 (如 MessagingStyle)。也就是說,系統負責確保套用正確的檢視畫面樣式。

小工具與自訂通知檢視畫面

針對啟動器小工具,或是如果您的應用程式使用自訂通知內容檢視畫面,請務必讓內容在淺色和深色主題都經過測試。

應留意的常見問題:

  • 假設背景顏色一律為淺色
  • 硬式編碼文字顏色
  • 設定硬式編碼背景顏色,同時使用預設文字顏色
  • 使用靜態色彩的可繪圖示

無論是哪一種情況,都請使用合適的主題屬性,而非硬式編碼色彩。

啟動畫面

如果您的應用程式有自訂啟動畫面,可能會需要加以修改,以對應所選主題。

請移除所有硬式編碼色彩,例如任何可能為白色的背景顏色,改用 ?android:attr/colorBackground 主題屬性。

請注意,深色主題 android:windowBackground 可繪項目僅適用於 Android 10。

設定變更

當應用程式的主題變更 (透過系統設定或 AppCompat) 時,即會觸發 uiMode 設定變更。也就是說,系統會自動重新建立活動。

在某些情況下,您可能會想要應用程式處理設定變更。例如,由於正在播放影片,因此您想要延遲設定變更。

應用程式會宣告每項活動皆可處理 uiMode 設定變更,以自行處理深色主題的實作:

<activity
    android:name=".MyActivity"
    android:configChanges="uiMode" />

當活動宣告可處理設定變更時,會在主題變更時呼叫其 onConfigurationChanged() 方法。

如要查看目前主題,應用程式可以執行下列程式碼:

Kotlin

val currentNightMode = configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
when (currentNightMode) {
    Configuration.UI_MODE_NIGHT_NO -> {} // Night mode is not active, we're using the light theme
    Configuration.UI_MODE_NIGHT_YES -> {} // Night mode is active, we're using dark theme
}

Java

int currentNightMode = configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK;
switch (currentNightMode) {
    case Configuration.UI_MODE_NIGHT_NO:
        // Night mode is not active, we're using the light theme
        break;
    case Configuration.UI_MODE_NIGHT_YES:
        // Night mode is active, we're using dark theme
        break;
}