在 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。此 API 仅在将强制深色设置为 FORCE_DARK_ONFORCE_DARK_AUTO 时适用。

使用此 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(...);
}

受支持的策略选项为

如果您的应用显示您使用 prefers-color-scheme 媒体查询自定义的第三方 Web 内容,我们建议使用 DARK_STRATEGY_WEB_THEME_DARKENING_ONLY,以确保 WebView 使用自定义主题。

有关应用深色主题的示例,请参见 GitHub 上的 WebView 演示