在 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) 以上版本為目標,請使用 Jetpack Webkit setAlgorithmicDarkeningAllowed() 方法,並傳遞 true,指定 WebView 應允許演算法調暗。這個方法可與舊版 Android 回溯相容。

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

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

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

如果應用程式未使用應用程式層級的強制使用深色主題,且指定 Android 12 (API 級別 32) 以下版本為目標,請使用 FORCE_DARK_ON 允許演算法調暗。

如果應用程式提供專屬的淺色和深色主題切換方法 (例如使用者介面中的可切換元素,或根據時間自動選取),請搭配使用 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;
    }
}

自訂深色主題處理方式

您也可以在 Jetpack 程式庫中使用 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 媒體查詢。您可以使用 DARK_STRATEGY_WEB_THEME_DARKENING_ONLY 模式的 WebView,在這種情況下,即使省略標記,WebView 一律會套用媒體查詢。

    不過,建議網頁開發人員在網站中加入 <meta name="color-scheme" content="dark light"> 標記,確保內容在採用預設設定的 WebView 中正確顯示。

  • DARK_STRATEGY_USER_AGENT_DARKENING_ONLY: 這項功能稱為「使用者代理程式調暗」,可讓 WebView 忽略任何網頁調暗設定,並自動調暗網頁。

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

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