在 WebView 中調暗網頁內容

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

WebView 的行為會與 prefers-color-schemecolor-scheme 網頁標準互通。如果可以編寫希望應用程式在 WebView 中顯示的網頁內容,請為網站定義深色主題並實作 prefers-color-scheme,讓 WebView 比對網頁內容的主題和應用程式的主題。

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

應用程式條件 使用 prefers-color-scheme 的網頁內容 不使用 prefers-color-scheme 的網頁內容
應用程式使用淺色主題,且 isLightTheme 設為 true 或未設為 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 示範