在 Android 10 及更高版本中,应用可以支持深色主题,并根据系统主题在浅色和深色应用主题之间自动切换。为了与当前应用主题相匹配,WebView 中的网页内容也可以使用浅色、深色或默认样式。
WebView 的行为与 prefers-color-scheme 和 color-scheme Web 标准相互配合。如果可能,如果您是应用在 WebView 中所显示的网页内容的作者,您应该为您的网站定义深色主题并实现 prefers-color-scheme,以便 WebView 能够将网页内容的颜色与您应用的主题相匹配。
下表根据网页内容的样式和您的应用条件,描述了 WebView 在您的应用中呈现网页内容的方式:
| 应用条件 | 使用 prefers-color-scheme 的网页内容 |
未使用 prefers-color-scheme 的网页内容 |
|---|---|---|
应用使用的是浅色主题,且 isLightTheme 设置为 true 或未设置。 |
WebView 使用内容作者定义的浅色主题呈现内容。 | WebView 使用内容作者定义的默认样式呈现内容。 |
| 应用正在使用“强制深色”(Force Dark) 以算法方式将深色主题应用于应用。 | WebView 使用内容作者定义的深色主题呈现内容。 | 如果内容作者允许,WebView 将使用通过算法生成的深色主题来呈现内容。 |
应用正在使用深色主题,且 isLightTheme 设置为 false,并且应用不允许为 WebView 进行算法变暗。 |
WebView 使用内容作者定义的深色主题呈现内容。 | WebView 使用内容作者定义的默认样式呈现内容。 |
应用正在使用深色主题,且 isLightTheme 设置为 false,并且应用允许为 WebView 进行算法变暗。 |
WebView 使用内容作者定义的深色主题呈现内容。 | 如果内容作者允许,WebView 将使用通过算法生成的深色主题来呈现内容。 |
内容作者定义的样式
应用的 isLightTheme 属性用于指明应用主题是浅色还是深色。WebView 始终会根据 isLightTheme 设置 prefers-color-scheme。如果 isLightTheme 为 true 或未指定,则 prefers-color-scheme 为 light;否则为 dark。
这意味着,如果网页内容使用了 prefers-color-scheme 且内容作者允许,则内容作者定义的浅色或深色主题始终会自动应用于网页内容,以匹配应用主题。
算法变暗
为了涵盖网页内容未使用 prefers-color-scheme 的情况,您的应用可以在必要时允许 WebView 以算法方式将深色主题应用于所呈现的网页内容。
如果您的应用正在使用应用级的“强制深色”(Force Dark) 来以算法方式将深色主题应用于您的应用,请参阅下一节,了解如何通过“强制深色”允许网页内容的算法变暗。
如果您的应用没有使用“强制深色”,则应用指定何时允许在 WebView 中进行算法变暗的方式取决于应用的目标 API 级别。有关详细信息,请参阅针对 Android 13 或更高版本以及 Android 12 或更低版本的应用的相应章节。
通过“强制深色”允许网页内容的算法变暗
如果您的应用正在使用应用级的“强制深色”(Force Dark),则在满足以下条件时,WebView 会对网页内容应用算法变暗:
- WebView 及其父元素允许“强制深色”。
- 当前 Activity 主题被标记为浅色,且
isLightTheme设置为true。 - 网页内容作者未明确禁用变暗功能。
- 对于目标 API 级别为 Android 13 (API 33) 或更高的应用,网页内容未使用
prefers-color-scheme。 - 对于目标 API 级别为 Android 12 (API 32) 或更低的应用:应用已将 WebView 的
forceDarkMode设置设为FORCE_DARK_AUTO,并将强制深色策略设为DARK_STRATEGY_USER_AGENT_DARKENING_ONLY。
WebView 及其所有父级可以使用 View.setForceDarkAllowed() 允许强制深色。默认值取自 Android 主题的 setForceDarkAllowed() 属性,该属性也必须设置为 true。
强制深色模式主要用于那些未提供自有深色主题的应用,以实现向后兼容。如果您的应用使用了“强制深色”,我们建议您添加对深色主题的支持。
允许算法变暗(针对 Android 13 或更高版本的应用)
对于未使用应用级“强制深色”且目标 API 级别为 Android 13 (API 33) 或更高的应用,请使用 Jetpack Webkit 的 setAlgorithmicDarkeningAllowed() 方法并传入 true,以指定 WebView 应允许算法变暗。此方法向后兼容以前的 Android 版本。
此时,若满足以下条件,WebView 将应用算法变暗:
- 网页内容未使用
prefers-color-scheme。 - 网页内容作者未明确禁用变暗功能。
允许算法变暗(针对 Android 12 或更低版本的应用)
对于未使用应用级“强制深色”且目标 API 级别为 Android 12 (API 32) 或更低的应用,请使用 FORCE_DARK_ON 来允许算法变暗。
如果您应用本身提供了切换浅色和深色主题的方法(例如 UI 中的切换开关或基于时间的选择),请将 FORCE_DARK_ON 与 FORCE_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_ON 和 FORCE_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 应用变暗。此 API 仅在强制深色设置为 FORCE_DARK_ON 或 FORCE_DARK_AUTO 时适用。
使用该 API,您的应用可以选择网页主题变暗或用户代理变暗:
- 网页主题变暗:Web 开发者可以使用
@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 也会始终应用媒体查询。不过,我们建议 Web 开发者在其网站中添加
<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 演示。