How do I force darken the WebView parent so that I can use WebSettingsCompat.FORCE_DARK_AUTO?

3.6k Views Asked by At

I've followed the instructions on this super useful answer https://stackoverflow.com/a/61643614/704836 and I have dark mode in the WebView implemented however WebSettingsCompat.FORCE_DARK_AUTO doesn't seem to work when I use AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) and this leads me to believe the documentation is talking about a different way of setting dark mode?

The documentation here https://developer.android.com/reference/androidx/webkit/WebSettingsCompat#FORCE_DARK_AUTO says:

Enable force dark dependent on the state of the WebView parent view. If the WebView parent view is being automatically force darkened (@see android.view.View#setForceDarkAllowed), then WebView content will be rendered so as to emulate a dark theme. WebViews that are not attached to the view hierarchy will not be inverted.

I've tried webView.setForceDarkAllowed(true) and android:forceDarkAllowed="true" on the parent layout and on the WebView and that didn't help. But as soon as I change to WebSettingsCompat.FORCE_DARK_ON then it works.

So how can I use FORCE_DARK_AUTO?

Thanks.

1

There are 1 best solutions below

3
On BEST ANSWER

Android Force Dark and Android DayNight themes are two different features.

  • Force Dark is meant to automatically turn "light-only" apps into dark mode apps by the system. It's meant as a quick fix for light-only apps to "support" dark mode. If your app is not light-only and already supports DayNight/Dark mode you should not (and basically cannot) use this feature.

  • Android DayNight themes are hybrid themes that automatically switch between their light and dark version based on the system theme or day/night mode settings. This is the recommended way to implement dark mode.

For some unexplained reason the WebKit/WebView developers decided to link the webview's FORCE_DARK_AUTO setting to the Android Force Dark feature but not to the recommended DayNight feature

As you stated your app is using a DayNight theme. Therefore the Android 10 Force Dark feature is disabled in your app and the FORCE_DARK_AUTO setting on your webview doesn't work.

So to enable automatic dark mode switching for your webview, you need to check in what mode your DayNight theme is running and then enable or disable the dark mode on the webview accordingly:

if(WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {

   int nightModeFlags = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;

   if (nightModeFlags == Configuration.UI_MODE_NIGHT_YES) {
       //Theme is switched to Night/Dark mode, turn on webview darkening
       WebSettingsCompat.setForceDark(myWebView.getSettings(), WebSettingsCompat.FORCE_DARK_ON);
   }
   else{
      //Theme is not switched to Night/Dark mode, turn off webview darkening
      WebSettingsCompat.setForceDark(myWebView.getSettings(), WebSettingsCompat.FORCE_DARK_OFF);
   }
}

Although not recommended, if you still want to drop your DayNight theme support and enable the Force Dark quick fix instead you can read some general info on Android 10's Force Dark feature below.

Android 10 Force Dark feature

Force Dark for Android is a feature introduced in Android 10 (API 29). It allows any app or activity that's using a light-only theme and therefore does not support dark mode by itself to automatically be darkened by the system when the device is running in dark mode.

Since you have no control over how this feature applies dark mode to your activities and components, it's only recommended to use if you need a "quick fix" to implement dark mode. If you want to implement dark mode properly in your app, you need to either use a dark theme or a auto-switching DayNight theme.

To enable force dark for your application it needs to:

  • Use or inherit from a light-only theme (<item name="isLightTheme">true</item> needs to be set for the theme or its ancestor)
  • <item name="android:forceDarkAllowed">true</item> needs to be set for your theme or its ancestor.
  • You need to have your compileSdkVersion (and possibly targetSdkVersion) in your build.gradle set to at least 29

Most system and AndroidX light-only themes (like android:Theme.Material.Light or Theme.MaterialComponents.Light) should have the light theme property set by default, so creating a theme inheriting from them like this should enable force dark:

<style name="AppTheme" parent="Theme.MaterialComponents.Light">
        <!-- Other properties here-->

        <item name="android:forceDarkAllowed">true</item>
</style>

And then apply that theme to your application (or a single activity) in the Android manifest

<application
    ...
    android:theme="@style/AppTheme">
</application>

This will enable force dark for the entire application or activity you have set the theme on. All views within it have force dark enabled by default now. You can opt-out individual views from force dark by setting android:forceDarkAllowed="false" on them.