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 temas claros y oscuros según el tema del sistema. Para que coincida 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 interactúa con los prefers-color-scheme y color-scheme estándares web. Cuando 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 para que WebView pueda hacer coincidir el tema del contenido web con el de tu app.

En la siguiente tabla, se describe cómo WebView renderiza el contenido web en tu app, según el estilo del contenido web y las condiciones de tu 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 configurado como true o no configurado. WebView renderiza el contenido con el tema claro que definió el autor del contenido. WebView renderiza el contenido con el estilo predeterminado que definió el autor del contenido.
La app usa Modo oscuro forzado para aplicar algorítmicamente un tema oscuro a la app. WebView renderiza el contenido con el tema oscuro que definió el autor del contenido. 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 configurado como false y la app no permite el oscurecimiento algorítmico para WebView. WebView renderiza el contenido con el tema oscuro que definió el autor del contenido. WebView renderiza el contenido con el estilo predeterminado que definió el autor del contenido.
La app usa un tema oscuro con isLightTheme configurado como false y la app permite el oscurecimiento algorítmico para WebView. WebView renderiza el contenido con el tema oscuro que definió el autor del contenido. Si el autor del contenido lo permite, WebView renderiza el contenido con un tema oscuro que se genera mediante un algoritmo.

Estilo del autor del contenido

El atributo isLightTheme de una app indica si el tema de la app es claro u oscuro. WebView siempre establece prefers-color-scheme según isLightTheme. Si isLightTheme es true o no se especifica, 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 claro u oscuro que definió el autor del contenido siempre se aplica automáticamente al contenido web para que coincida con el tema de la app.

Oscurecimiento algorítmico

Para cubrir los 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 a tu app, consulta la siguiente sección en la que se describe cómo permitir el oscurecimiento algorítmico para el contenido web con Forzar oscuro.

Si tu app no usa Forzar oscuro, la forma en que especifica cuándo permitir el oscurecimiento algorítmico en WebView depende del nivel de API objetivo de tu app . Consulta las siguientes secciones para obtener detalles sobre las apps orientadas a Android 13 o versiones posteriores y apps orientadas a Android 12 o versiones anteriores.

Permite el oscurecimiento algorítmico para el contenido web con Modo oscuro forzado

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

  • WebView y sus elementos superiores permiten el Modo oscuro forzado.
  • El tema de la actividad actual se marca como claro con isLightTheme configurado como true.
  • El autor del contenido web no inhabilita explícitamente el oscurecimiento.
  • En el caso de las apps orientadas 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 configuró el parámetro WebView's forceDarkMode setting como FORCE_DARK_AUTO y estableció su estrategia de Modo oscuro forzado como DARK_STRATEGY_USER_AGENT_DARKENING_ONLY.

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

El modo oscuro forzado se proporciona principalmente para la retrocompatibilidad en apps que no proporcionan su propio tema oscuro. Si tu app usa Modo oscuro forzado, te recomendamos que agregues compatibilidad con un tema oscuro.

Permite el oscurecimiento algorítmico (apps orientadas a Android 13 o versiones posteriores)

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

Luego, WebView aplica el 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.

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

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

Use FORCE_DARK_ON together with FORCE_DARK_OFF if your app provides its own method for switching between light and dark themes, such as a toggleable element in the UI or an automatic time-based selection.

Para verificar si se admite la función, agrega las siguientes líneas de código donde 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, debe 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 la biblioteca de Jetpack para controlar cómo se aplica el oscurecimiento a un WebView determinado. Esta API solo se aplica si Forzar oscuro está configurado como FORCE_DARK_ON o FORCE_DARK_AUTO.

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

  • Oscurecimiento del tema web: Los desarrolladores web pueden aplicar @media (prefers-color-scheme: dark) para controlar la apariencia de la página web en el modo oscuro. WebView renderiza el contenido según esta configuración. Para obtener más información sobre el oscurecimiento del tema web, consulta la especificación.
  • Oscurecimiento del agente de usuario: WebView invierte automáticamente los colores de la página web. Si usas el oscurecimiento del agente de usuario, 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 compatibles 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 tratan la <meta name="color-scheme" content="dark light"> etiqueta como opcional, el modo predeterminado de Android WebView's requiere que la etiqueta meta respete las consultas de medios prefers-color-scheme de la página web. Puedes usar WebViews con DARK_STRATEGY_WEB_THEME_DARKENING_ONLY modo, en cuyo caso WebView siempre aplica consultas de medios, incluso si se omite la etiqueta.

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

  • DARK_STRATEGY_USER_AGENT_DARKENING_ONLY: Llamado "oscurecimiento del agente de usuario", WebView ignora cualquier oscurecimiento de la página web y aplica el oscurecimiento automático.

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

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