在 WebView 中調暗網頁內容

在 Android 10 以上版本中,應用程式可以支援深色主題,並會根據系統主題自動在淺色和深色主題應用程式主題之間切換。為了與目前的應用程式主題相符,WebView 中的網頁內容也可以使用淺色、深色或預設樣式。

WebView 的行為與 prefers-color-schemecolor-scheme 網路標準互通。如果您編寫了希望應用程式在 WebView 中顯示的網路內容,請盡可能為網站定義深色主題並實作 prefers-color-scheme,讓 WebView 將網頁內容的主題與您應用程式的主題相符。

下表說明 WebView 如何根據網頁內容樣式和應用程式條件,在應用程式中算繪網路內容:

應用程式條件 使用 prefers-color-scheme 的網路內容 沒有使用「prefers-color-scheme」的網路內容
應用程式使用的淺色主題有 isLightTheme 設為 true 或未設定。 WebView 會以淺色主題 (內容作者定義) 算繪內容。 WebView 會以內容作者定義的預設樣式來算繪內容。
應用程式正在使用強制使用深色功能,藉此透過演算法將深色主題套用至應用程式 WebView 會以內容作者定義的深色主題來算繪內容。 如果內容作者允許,WebView 會以演算法產生的深色主題轉譯內容。
應用程式使用的深色主題是 isLightTheme 設為 false,但應用程式不允許 WebView 使用演算法調暗。 WebView 會以內容作者定義的深色主題來算繪內容。 WebView 會以內容作者定義的預設樣式來算繪內容。
應用程式使用的深色主題是 isLightTheme 設為 false,但應用程式允許 WebView 的演算法調暗 WebView 會以內容作者定義的深色主題來算繪內容。 如果內容作者允許,WebView 會以演算法產生的深色主題轉譯內容。

內容作者樣式設定

應用程式的 isLightTheme 屬性會指出應用程式的主題是淺色或深色。WebView 一律會根據 isLightTheme 設定 prefers-color-scheme。如果 isLightThemetrue 或未指定,則 prefers-color-schemelight;否則為 dark

也就是說,如果網頁內容使用 prefers-color-scheme,且內容作者允許,內容作者定義的淺色或深色主題一律會自動套用至網路內容,以符合應用程式主題。

演算法調暗

為了涵蓋網頁內容不使用 prefers-color-scheme 的情況,應用程式可以在必要時允許 WebView 透過演算法對轉譯的網路內容套用深色主題。

如果您的應用程式使用應用程式層級的「強制使用深色模式」,透過演算法將深色主題套用至應用程式,請參閱下一節,瞭解如何使用強制使用深色的演算法針對網頁內容進行演算法調暗

如果您的應用程式未使用強制深色模式,應用程式會如何指定在 WebView 中允許演算法調暗的時機,取決於應用程式的目標 API 級別。詳情請參閱指定 Android 13 以上版本的應用程式指定 Android 12 以下版本的應用程式

允許使用「強制深色模式」對網路內容進行演算法調暗

如果您的應用程式使用應用程式層級的強制使用深色功能,則在符合下列條件的情況下,WebView 會對網路內容套用演算法調暗:

  • WebView 及其父項元素允許「強制使用深色模式」。
  • 目前的活動主題會標示為淺色,並將 isLightTheme 設為 true
  • 網頁內容作者並未明確停用調暗功能。
  • 如果應用程式指定 Android 13 (API 級別 33) 以上版本為目標,網頁內容不會使用 prefers-color-scheme
  • 指定 Android 12 (API 級別 32) 以下版本的應用程式:應用程式已將 WebView 的 forceDarkMode 設定設為 FORCE_DARK_AUTO,並已將「強制使用深色」策略設為 DARK_STRATEGY_USER_AGENT_DARKENING_ONLY

WebView 和所有父項皆可使用 View.setForceDarkAllowed() 強制使用深色模式。預設值取自 Android 主題的 setForceDarkAllowed() 屬性,此屬性也必須設為 true

強制深色模式主要用於回溯相容性,用於未提供深色主題的應用程式。如果您的應用程式使用強制使用深色模式,建議您新增深色主題的支援

允許演算法調暗 (指定 Android 13 以上版本的應用程式)

如果應用程式未使用應用程式層級「強制使用深色模式」,並指定 Android 13 (API 級別 33) 以上版本,請使用 AndroidX setAlgorithmicDarkeningAllowed() 方法並傳入 true,以指定 WebView 應允許演算法調暗。這個方法與先前的 Android 版本回溯相容。

接著,如果符合下列條件,WebView 就會套用演算法調暗:

  • 網路內容沒有使用 prefers-color-scheme
  • 網頁內容作者並未明確停用調暗功能。

允許演算法調暗 (指定 Android 12 以下版本的應用程式)

如果應用程式未使用應用程式層級「強制使用深色模式」,並指定 Android 12 (API 級別 32) 以下版本,請使用 FORCE_DARK_ON 允許演算法調暗。

如果您的應用程式提供單獨切換淺色和深色主題的方法 (例如 UI 中的可切換元素,或以時間為準的自動選取項目),請搭配使用 FORCE_DARK_ONFORCE_DARK_OFF

如要檢查是否支援這項功能,請在設定 WebView 物件的地方加入以下幾行程式碼,例如在 Activity.onCreate 中:

Kotlin

if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
    WebSettingsCompat.setForceDark(...)
}

Java

if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
    WebSettingsCompat.setForceDark(...);
}

如果應用程式需要偵測系統偏好設定的變更,則應用程式應明確監聽主題變更,並套用至具有 FORCE_DARK_ONFORCE_DARK_OFF 狀態的 WebView。

以下程式碼片段說明如何變更主題格式:

Kotlin

if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
    when (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) {
        Configuration.UI_MODE_NIGHT_YES -> {
            WebSettingsCompat.setForceDark(myWebView.settings, FORCE_DARK_ON)
        }
        Configuration.UI_MODE_NIGHT_NO, Configuration.UI_MODE_NIGHT_UNDEFINED -> {
            WebSettingsCompat.setForceDark(myWebView.settings, FORCE_DARK_OFF)
        }
        else -> {
            //
        }
    }
}

Java

if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
    switch (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) {
        case Configuration.UI_MODE_NIGHT_YES:
            WebSettingsCompat.setForceDark(myWebView.getSettings(), FORCE_DARK_ON);
            break;
        case Configuration.UI_MODE_NIGHT_NO:
        case Configuration.UI_MODE_NIGHT_UNDEFINED:
            WebSettingsCompat.setForceDark(myWebView.getSettings(), FORCE_DARK_OFF);
            break;
    }
}

自訂深色主題處理方式

您也可以使用 AndroidX 中的 ForceDarkStrategy API 控制特定 WebView 套用調暗方式的方式。只有在強制深色設為 FORCE_DARK_ONFORCE_DARK_AUTO 時,才能使用這個 API。

透過這個 API,應用程式可以使用網路主題調暗或使用者代理程式調暗:

  • 網頁主題調暗:網頁開發人員可套用 @media (prefers-color-scheme: dark),控制在深色模式下的網頁外觀。WebView 會根據這些設定算繪內容。如要進一步瞭解網路主題調暗功能,請參閱規格
  • 使用者代理程式調暗:WebView 會自動反轉網頁顏色。如果您使用使用者代理程式調暗,@media (prefers-color-scheme: dark) 查詢會評估為 false

如果您想選擇其中一種策略,請使用以下 API:

Kotlin

if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK_STRATEGY)) {
    WebSettingsCompat.setForceDarkStrategy(...)
}

Java

if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK_STRATEGY)) {
    WebSettingsCompat.setForceDarkStrategy(...);
}

支援的策略選項如下:

  • DARK_STRATEGY_PREFER_WEB_THEME_OVER_USER_AGENT_DARKENING:這是預設選項。雖然大多數瀏覽器會將 <meta name="color-scheme" content="dark light"> 標記視為選用,但 Android WebView 的預設模式需要中繼標記,以遵循網頁的 prefers-color-scheme 媒體查詢。您可以將 WebView 與 DARK_STRATEGY_WEB_THEME_DARKENING_ONLY 模式搭配使用,在這種情況下,即使缺少標記,WebView 一律會套用媒體查詢。

    不過,我們建議網頁開發人員在自家網站中加入 <meta name="color-scheme" content="dark light"> 標記,確保內容使用預設設定正確轉譯在 WebView 中。

  • DARK_STRATEGY_USER_AGENT_DARKENING_ONLY:WebView 會忽略「使用者代理程式調暗」功能,忽略所有網頁調暗並套用自動調暗功能。

如果應用程式會顯示您使用 prefers-color-scheme 媒體查詢自訂的第一方網路內容,建議您使用 DARK_STRATEGY_WEB_THEME_DARKENING_ONLY,確保 WebView 使用自訂主題。

如需套用深色主題的範例,請參閱 GitHub 上的 WebView 示範