Android Studio 让Android上的WebView使用首选颜色方案:暗的

2ekbmq32  于 2022-11-16  发布在  Android
关注(0)|答案(6)|浏览(615)

我有一个使用webview的Android应用程序,最近我正在尝试使用新的@media (prefers-color-scheme: dark) CSS语法来添加一个深色主题。我在页面上写了正确的CSS,如果我在Chrome中打开它,并打开Chrome的深色模式,它就可以工作了。我还让我的AppTheme继承了Theme.AppCompat.DayNight。当我在我的设备上打开整个操作系统的暗模式时,我的应用程序显示暗加载对话框等。甚至<input>元素的自动完成选项也变暗了。但是,用我的webview加载的网页仍然没有变暗。根据this page,webviews应该支持这个特性,但是我就是不能让它工作。我错过了什么?
我还发现在API 29中有WebSettings.setForceDark()方法;这可能是我正在寻找的东西吗?我希望找到一个解决方案,工作与较低的API水平虽然。
顺便说一下,我目前的解决方法是注入一个JavaScript接口,如下所示:

webView.addJavascriptInterface(new JSInterface(), "jsInterface");

...

public class JSInterface {
    @JavascriptInterface
    public boolean isNightMode() {
        int nightModeFlags = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
        return nightModeFlags == Configuration.UI_MODE_NIGHT_YES;
    }
}

然后在我的网页中,调用jsInterface.isNightMode()方法,并根据结果动态加载不同的CSS文件。它当然工作,并按预期响应全局黑暗模式设置,但我仍然怀疑我是否能让prefers-color-scheme工作。

368yc8dk

368yc8dk1#

2022年更新:AndroidX Webkit 1.5.0修复了webview处理黑暗模式的很多古怪之处。

要使其正常工作,您需要:

  • 将最新版本的webkit添加到您的项目(至少为1.5.0):
  • implementation 'androidx.webkit:webkit:1.5.0'
  • 将应用程序的目标版本设置为33或更高版本
  • targetSdkVersion 33
  • 确保设备上安装了Android System Webview v100或更高版本

通过此设置,webview将根据应用主题进行适当调整,而无需调整任何进一步的设置。prefers-color-scheme CSS查询值将根据当前Activity/fragment正在运行的主题类型(亮/暗)自动调整为亮或暗。
如果您的应用targetSdkVersion设置为33或更高,则用于调整暗模式的API 33之前的方法(WebViewSettingsCompat.setForceDarkWebViewSettingsCompat.setForceDarkStrategy等)是无效的,可以从您的代码中删除。

**注意:**此新方法要求您的应用面向API 33或更高版本,但向后兼容API 29(首个支持黑暗模式的Android版本)。
**注2:**用户代理变暗(对于不支持变暗得网页,自动变暗模式)现在在大多数情况下默认为禁用,但可以使用以下方法启用:

if(WebViewFeature.isFeatureSupported(WebViewFeature.ALGORITHMIC_DARKENING)) {
    WebSettingsCompat.setAlgorithmicDarkeningAllowed(myWebView.getSettings(), true);
}

有关此方法行为的完整说明,请参阅此处

传统方法(面向API 32或更低版本,或使用旧版AndroidX webkit的应用)

API 32及以下版本的Android Webview处理白天/夜晚模式的方式与其他视图稍有不同。将主题设置为深色会将WebView组件(滚动条、缩放按钮等)更改为深色模式版本,但不会更改加载的内容。
要更改内容,您需要使用webview设置的setForceDark方法来更改其内容。此方法的兼容版本可以在AndroidX webkit包中找到。
将以下依赖项添加到您的gradle构建:

implementation 'androidx.webkit:webkit:1.3.0'

(1.3.0是此软件包的最低要求版本。但更高版本也可以。)
并将以下代码行添加到WebView初始化中:

if(WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
    WebSettingsCompat.setForceDark(myWebView.getSettings(), WebSettingsCompat.FORCE_DARK_ON);
}

isFeatureSupported检查是为了确保用户在设备上安装的Android System WebView版本支持黑暗模式(因为这可以通过Google Play独立于Android版本进行更新或降级)。

注:setForceDark功能要求在运行的设备上安装Android System WebViewv76或更高版本。

Webview内容的强制黑暗功能有两个所谓的策略:

***用户代理变暗:**webview将通过自动反转或变暗其内容的颜色来将其内容设置为暗模式。
***基于主题的暗化:**网络视图将根据内容的主题(包括@media (prefers-color-scheme: dark)查询)更改为暗模式。

要设置webview应用强制变暗的策略,可以使用以下代码:

if(WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK_STRATEGY)) {
    WebSettingsCompat.setForceDarkStrategy(myWebView.getSettings(), WebSettingsCompat.DARK_STRATEGY_WEB_THEME_DARKENING_ONLY);
}

注:策略选择要求在运行设备上安装Android System WebViewv83或更高版本。支持setForceDark但不支持策略选择(v76至v81)的WebView版本将使用用户代理变暗

支持的策略选项包括:

*仅限变暗策略用户代理变暗:仅使用用户代理变暗并忽略内容中的任何主题(默认)
*仅限深策略网页主题加深:只使用内容本身的深色主题来将页面设置为深色模式。如果内容没有深色主题,网页视图将不会应用任何深色化,而是“原样”显示。
*策略首选网页主题超过用户代理变暗:使用内容本身的深色主题将页面设置为深色模式。如果内容没有深色主题,请使用用户代理变暗。
Javascript检查如何处理变暗的Web视图?

JavaScript调用window.matchMedia('(prefers-color-scheme: dark)')将在用户代理变暗和web主题变暗策略中匹配。

我的网络视图设置为FORCE_DARK_AUTO,并且我的应用在日间和夜间主题下运行,但不知何故,我的网络视图没有根据我的应用主题自动应用黑暗模式。为什么会发生这种情况?

这是因为webview的FORCE_DARK_AUTO设置值不基于主题工作(如文档中所述)。它检查Android 10强制黑暗功能(应用的“快速修复”黑暗模式功能。它的名称类似,但与WebView强制黑暗没有直接关系)。
如果你没有使用强制变暗,而是使用了一个应用主题来处理黑暗模式(推荐),你必须自己检查何时应用网页视图的强制变暗功能。

int nightModeFlags = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
if (nightModeFlags == Configuration.UI_MODE_NIGHT_YES) {
   //Code to enable force dark using FORCE_DARK_ON and select force dark strategy 
}
qqrboqgw

qqrboqgw2#

我所做的,基于你的问题代码,是强制基于当前状态:

int nightModeFlags = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
if (nightModeFlags == Configuration.UI_MODE_NIGHT_YES) {
  webSettings.setForceDark(WebSettings.FORCE_DARK_ON);
}

这样@media (prefers-color-scheme: dark)就可以工作了,但是@media (prefers-color-scheme: light)仍然不能工作(尝试在else中使用FORCE_DARK_OFFFORCE_DARK_AUTO

z31licg0

z31licg03#

这里有两个相关的文档:
https://developer.android.com/guide/topics/ui/look-and-feel/darktheme#force_dark
https://developer.android.com/reference/android/view/View.html#setForceDarkAllowed(boolean)
要点是

  1. WebView必须允许强制变暗,其所有父级也必须允许。
    1.主题必须标记为浅色。
    这意味着在WebView中使用FORCE_DARK_AUTO行为有点复杂。在AppCompat.DayNight主题中添加以下内容确实有效,但可能不是最好的解决方案,因为它可能会将Android强制黑暗应用于WebView以外的视图。
<item name="android:forceDarkAllowed">true</item>
<item name="android:isLightTheme">true</item>

另一个选项是手动处理此问题,方法是根据相关配置更改设置FORCE_DARK_ON/OFF。
目前,WebView不支持prefers-color-scheme,部分原因是强制暗是在prefers-color-scheme标准化之前实现的,部分原因是没有办法将其与强制暗进行合理的集成(没有样式闪烁)。其目的是通过androidx. webkit提供选择强制暗或prefers-color-scheme的能力。

cx6n0qe3

cx6n0qe34#

implementation 'androidx.webkit:webkit:1.4.0'

WebSettings settings = webView.getSettings();

if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
   if (isNightMode) {
      WebSettingsCompat.setForceDark(settings, WebSettingsCompat.FORCE_DARK_ON);
   } else {
      WebSettingsCompat.setForceDark(settings, WebSettingsCompat.FORCE_DARK_OFF);
   }
}
x7rlezfr

x7rlezfr5#

我不认为WebView支持首选配色方案CSS媒体查询。
setForceDark的新API有三种状态:开、关或自动。
开-每次都将内容渲染得更暗。
关闭-您的内容将始终呈现光每次。
自动-如果您的应用的主题较暗,或者由于用户切换操作系统级别开关或打开节电模式而导致设备操作系统处于暗模式,则内容将渲染为较暗。
我相信对旧版本Android的支持,以及是否使用首选配色方案而不是WebView的强制黑暗的控制,很快就会通过AndroidX来实现。
目前我建议将WebView设置为SetForceDark Auto。这将在Android Q及以上版本上工作。
我会密切关注AndroidX发布说明,了解您对Android P及以下版本设备所需的其余支持。

1aaf6o9v

1aaf6o9v6#

对于最高版本为v93的Webview(实现“androidx.webkit:webkit:1.4.0”),标志DARK_STRATEGY_PREFER_WEB_THEME_OVER_USER_AGENT_DARKENING在我使用以下代码之前不起作用:

if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
            if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK_STRATEGY)){            
            WebSettingsCompat.setForceDarkStrategy(
                webView.settings,
                WebSettingsCompat.DARK_STRATEGY_WEB_THEME_DARKENING_ONLY
            )
        }
        WebSettingsCompat.setForceDark(webView.settings, WebSettingsCompat.FORCE_DARK_ON)
    }    
webView.evaluateJavascript("document.documentElement.setAttribute('data-color-mode', 'dark');", null)

这要求站点的深色主题,但不强制颜色反转。

相关问题