Cómo oscurecer contenido web en WebView

En Android 10 y versiones posteriores, una app puede admitir un Tema oscuro y cambiar automáticamente entre el tema claro y el oscuro para la app según el tema del sistema. Para coincidir con el tema actual de la app, el contenido web en WebView también puede usar un estilo claro, oscuro o predeterminado.

El comportamiento de WebView interopera con los estándares web prefers-color-scheme y color-scheme. Siempre que sea posible, si creas el contenido web que quieres que tu app muestre en WebView, debes definir un tema oscuro para tu sitio web y, luego, implementar prefers-color-scheme, de modo que WebView pueda coincidir con el tema de tu app.

En la siguiente tabla, se describe cómo WebView renderiza contenido web en tu app, según el estilo del contenido web y las condiciones de la app:

Condiciones de la app Contenido web que usa prefers-color-scheme Contenido web que no usa prefers-color-scheme
La app usa un tema claro con isLightTheme establecido en true o sin establecer. WebView procesa el contenido con el tema claro que el autor del contenido definió. WebView renderiza el contenido con el estilo predeterminado definido por el autor del contenido.
La app usa la función Forzar oscuro para aplicar algorítmicamente un tema oscuro. WebView procesa el contenido con el tema oscuro que el autor del contenido definió. Si el autor del contenido lo permite, WebView renderiza el contenido con un tema oscuro que se genera mediante un algoritmo.
La app usa un tema oscuro con isLightTheme establecido en false y no permite el oscurecimiento algorítmico para WebView. WebView procesa el contenido con el tema oscuro que el autor del contenido definió. WebView renderiza el contenido con el estilo predeterminado definido por el autor del contenido.
La app usa un tema oscuro con isLightTheme establecido en false y permite el oscurecimiento algorítmico para WebView. WebView procesa el contenido con el tema oscuro que el autor del contenido definió. Si el autor del contenido lo permite, WebView renderiza el contenido con un tema oscuro que se genera mediante un algoritmo.

Estilos de autor del contenido

El atributo isLightTheme de una app indica si el tema es oscuro o claro. WebView siempre establece prefers-color-scheme de acuerdo con isLightTheme. Si isLightTheme es true o no se especifica, entonces prefers-color-scheme es light; de lo contrario, es dark.

Esto significa que, si el contenido web usa prefers-color-scheme y el autor del contenido lo permite, el tema oscuro o claro definido por este siempre se aplica automáticamente al contenido web para que coincida con el tema de la app.

Oscurecimiento algorítmico

Para cubrir casos en los que el contenido web no usa prefers-color-scheme, tu app puede permitir que WebView, cuando sea necesario, aplique algorítmicamente un tema oscuro al contenido web que renderiza.

Si tu app usa Forzar oscuro a nivel de la app para aplicar algorítmicamente un tema oscuro, consulta la siguiente sección, en la que se describe cómo permitir el oscurecimiento algorítmico para contenido web con la función Forzar oscuro.

Si tu app no usa la función Forzar oscuro, la forma en que la app especifique cuándo permitir el oscurecimiento algorítmico en WebView dependerá del nivel de API objetivo de la app. Consulta las siguientes secciones sobre las apps que se orientan a Android 13 o versiones posteriores y las apps que se orientan a Android 12 o versiones anteriores para obtener más detalles.

Permitir el oscurecimiento algorítmico para el contenido web con Forzar oscuro

Si tu app usa Forzar oscuro a nivel de la app, WebView aplica un oscurecimiento algorítmico al contenido web si se cumplen las siguientes condiciones:

  • WebView y sus elementos superiores permiten usar la función Forzar oscuro.
  • El tema de la actividad actual se marcará como claro con isLightTheme establecido en true.
  • El autor del contenido web no inhabilita explícitamente el oscurecimiento.
  • En el caso de las apps que se orientan a Android 13 (nivel de API 33) o versiones posteriores, el contenido web no usa prefers-color-scheme.
  • En el caso de las apps orientadas a Android 12 (nivel de API 32) o versiones anteriores, la app estableció la configuración forceDarkMode de WebView en FORCE_DARK_AUTO y estableció la estrategia para forzar el modo oscuro en DARK_STRATEGY_USER_AGENT_DARKENING_ONLY.

WebView y todos sus elementos superiores pueden permitir forzar la oscuridad con View.setForceDarkAllowed(). El valor predeterminado se toma del atributo setForceDarkAllowed() del tema de Android, que también debe establecerse en true.

Esta función se proporciona principalmente para brindar retrocompatibilidad en apps que no proporcionan su propio tema oscuro. Si tu app usa la función para forzar el modo oscuro, te recomendamos que agregues compatibilidad con un tema oscuro.

Permitir el oscurecimiento algorítmico (apps que se orientan a Android 13 o versiones posteriores)

En el caso de las apps que no utilizan Forzar oscuro a nivel de la app y se orientan a Android 13 (nivel de API 33) o versiones posteriores, usa el método setAlgorithmicDarkeningAllowed() de AndroidX y pasa true para especificar que una WebView debe permitir el oscurecimiento algorítmico. Este método tiene retrocompatibilidad con versiones anteriores de Android.

Luego, WebView aplica un oscurecimiento algorítmico si se cumplen las siguientes condiciones:

  • El contenido web no usa prefers-color-scheme.
  • El autor del contenido web no inhabilita explícitamente el oscurecimiento.

Permitir el oscurecimiento algorítmico (apps orientadas a Android 12 o versiones anteriores)

En el caso de las apps que no utilizan la opción Forzar oscuro a nivel de la app y se orientan a Android 12 (nivel de API 32) o versiones anteriores, usa FORCE_DARK_ON para permitir el oscurecimiento algorítmico.

Usa FORCE_DARK_ON junto con FORCE_DARK_OFF si tu app proporciona su propio método para alternar entre los temas claro y oscuro, como un elemento que se puede activar o desactivar en la IU o una selección automática basada en el tiempo.

Para verificar si la función es compatible, agrega las siguientes líneas de código en cualquier lugar en el que configures tu objeto WebView, como en Activity.onCreate:

Kotlin

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

Java

if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
    WebSettingsCompat.setForceDark(...);
}

Si tu app depende de la detección de cambios en las preferencias del sistema, deberá escuchar explícitamente los cambios de tema y aplicarlos a WebView con los estados FORCE_DARK_ON y FORCE_DARK_OFF.

En el siguiente fragmento de código, se muestra cómo cambiar el formato del tema:

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;
    }
}

Personaliza el control del tema oscuro

También puedes usar la API de ForceDarkStrategy en AndroidX para controlar cómo se aplica el oscurecimiento a una WebView determinada. Esta API solo se aplica si se configura forzar el modo oscuro en FORCE_DARK_ON o FORCE_DARK_AUTO.

Con la API, tu app puede usar el oscurecimiento del tema web o el oscurecimiento del usuario-agente:

  • Oscurecimiento del tema web: Los desarrolladores web pueden aplicar @media (prefers-color-scheme: dark) para controlar la apariencia de las páginas web en modo oscuro. WebView renderiza contenido de acuerdo con esta configuración. Para obtener más información sobre el oscurecimiento del tema web, consulta la especificación.
  • Oscurecimiento del usuario-agente: WebView invierte automáticamente los colores de la página web. Si usas el oscurecimiento de usuario-agente, la consulta @media (prefers-color-scheme: dark) se evalúa como false.

Para elegir entre las dos estrategias, usa la siguiente API:

Kotlin

if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK_STRATEGY)) {
    WebSettingsCompat.setForceDarkStrategy(...)
}

Java

if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK_STRATEGY)) {
    WebSettingsCompat.setForceDarkStrategy(...);
}

Las opciones de estrategia admitidas son las siguientes:

  • DARK_STRATEGY_PREFER_WEB_THEME_OVER_USER_AGENT_DARKENING: Esta es la opción predeterminada. Si bien la mayoría de los navegadores consideran la etiqueta <meta name="color-scheme" content="dark light"> como opcional, el modo predeterminado de WebView de Android requiere que la metaetiqueta respete las consultas de medios prefers-color-scheme de la página web. Puedes usar WebViews con el modo DARK_STRATEGY_WEB_THEME_DARKENING_ONLY, en cuyo caso WebView siempre aplicará consultas de medios, incluso si se omite la etiqueta.

    Sin embargo, recomendamos que los desarrolladores web agreguen la etiqueta <meta name="color-scheme" content="dark light"> a sus sitios web para asegurarse de que el contenido se renderice correctamente en WebViews con la configuración predeterminada.

  • DARK_STRATEGY_USER_AGENT_DARKENING_ONLY: Se llama "oscurecimiento usuario-agente", y WebView ignora el oscurecimiento de cualquier página web y aplica el oscurecimiento automático.

Si tu app muestra contenido web propio que personalizaste con la consulta de medios prefers-color-scheme, te recomendamos DARK_STRATEGY_WEB_THEME_DARKENING_ONLY para asegurarte de que WebView use el tema personalizado.

Para ver un ejemplo de tema oscuro aplicado, consulta la demostración de WebView en GitHub.