Enabling dark theme in Android WebViews

So your apps just implemented a shiny new dark theme and it’s looking 👌 And if you haven’t yet, maybe it’s in the pipeline for you to work on sometime in the future! There are lots of benefits to having a dark theme in your application, and having it consistent throughout your application allows for a great user experience. But what happens when the the user runs into a WebView in your app? Even with dark themes correctly implemented, webviews will still render the content in the default light mode that we see as standard in our browsers – breaking our dark theme experience for the user.

But there is good news! The androidx.webkit package has recently worked on adding support for dark theming within WebViews – allowing us to provide a consistent dark theme experience throughout our application. To get started with androidx.webkit we need to begin by adding the dependency to our application:

implementation "androidx.webkit:webkit:1.2.0-alpha01"

The current stable release of androidx.webkit is version 1.1.0 however, dark mode support has been added in the latest alpha release, 1.2.0-alpha01. Within this version of webkit there are a few additions that make the interactions with dark mode settings a small amount of effort.

Within this webkit is a class called WebViewFeature – this is a collection of available features that can be accessed, and within this collection of features is FORCE_DARK. However, before we try and access this feature in any way we need to be sure that it is supported in the current situation that the webview is being used in. For this, the WebViewFeature class also contains an isFeatureSupported() function, which can be used to check if a given feature is supported. So before we go ahead and set the support for dark mode we’re going to want to check if it is supported:

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

Under the hood this isFeatureSupported function will check that FORCE_DARK is supported by both the framework and the webview being used. If this is the case then we can go ahead and configure the mode that we wish to use when it comes to the theming of the webview. When it comes to configuring this mode, there are 3 different options that are available:

  • FORCE_DARK_OFF – Disable the force dark mode for the webview, meaning the content of the webview will be rendered as-is
  • FORCE_DARK_ON – Enable the force dark mode for the webview, meaning the content of the webview will always be rendered with a dark theme
  • FORCE_DARK_AUTO – Enable the force dark mode for the webview depending on the state of the parent view, meaning that the system dark mode setting will be followed when rendering the content of the webview.

When it comes to using FORCE_DARK_AUTO and it following the system settings, it might help to be aware of when this might apply. There are a couple of examples of when this setting would kick in and follow the system configuration for dark theming:

  • Your application supports day/night theming*
  • Your application sets the default night mode using AppCompatDelegate.MODE_NIGHT_YES
  • Your application has enabled the android:forceDarkEnabled attribute from within your application theme

*currently with a day/night theme enabled this isn’t working for me with the expected behaviour – so please check back here for updates 🙌

Using one of the above values we can call the setForceDark() function from the WebSettingsCompat class, passing in a reference to the WebSettings value for our webview along with the dark mode that we wish to apply.

WebSettingsCompat.setForceDark(webView.settings, WebSettingsCompat.FORCE_DARK_ON)

With that set, we should be able to run our application and see that our webview is rendering its content using a dark theme. By default the FORCE_DARK_AUTO mode will be used, but with the above options we are able to set the dark mode depending on our needs.

In some cases you may need to retrieve the dark mode setting that is being used for a given webview. When so, the WebSettingsCompat class can be used to retrieve the current setting using its getForceDark function. All we need to provide here is a reference to our webviews WebSettings value:

val forceDarkMode = WebSettingsCompat.getForceDark(webView.settings)

In this post we’ve taken a look at the one of the additions to the 1.2.0 release of the androidx webkit package, dark mode settings. With these settings we’ll not only be able to provide a dark themed webview that will help to make the theming of our application more consistent, but also have a great level of control over how those settings operate.

Do you have a use case in mind as to where you’ll be able to use this? Or maybe you have some questions on how to make use of it. Either way, please feel free to reach out in the comments or on twitter!

[twitter-follow screen_name=’hitherejoe’ show_count=’yes’]