WebView con píxeles perfectos

Fecha de publicación: 28 de febrero de 2014

Existen varias opciones que puedes usar para crear la interfaz perfecta para tu WebView.

Configura la metaetiqueta de la vista del puerto

La metaetiqueta de viewport es una de las más importantes que se pueden agregar a tu app web. Sin ella, WebView puede actuar como si tu sitio estuviera diseñado para navegadores para computadoras de escritorio. Esto hace que tu página web tenga un ancho mayor (por lo general, 980 px) y la ajusta para que se ajuste al ancho de WebView. En la mayoría de los casos, esto genera una versión resumida de la página que requiere que el usuario realice panorámicas y zoom para leer el contenido.

Si deseas que el ancho de tu sitio sea el 100% del ancho de WebView, configura la metaetiqueta de viewport:

<meta name="viewport" content="width=device-width, initial-scale=1">

Establece el ancho en el valor especial device-width para obtener más control sobre el diseño de la página.

De forma predeterminada, WebView establece el viewport en el ancho del dispositivo, en lugar de usar un viewport para computadoras de escritorio. Sin embargo, para obtener un comportamiento confiable y controlado, se recomienda incluir la metaetiqueta del viewport.

Cómo mostrar sitios para computadoras

En algunos casos, es posible que debas mostrar contenido que no está diseñado para dispositivos móviles. Por ejemplo, puedes mostrar contenido que no controlas. En este caso, puedes forzar a WebView a usar un viewport del tamaño de una computadora de escritorio:

Si no se configuran estos métodos y no se especifica ningún viewport, WebView intentará establecer el ancho del viewport según el tamaño del contenido.

Además, te recomendamos que uses el algoritmo de diseño TEXT_AUTOSIZING, que aumenta el tamaño de la fuente para que sea más legible en un dispositivo móvil. Consulta setLayoutAlgorithm.

Usa el diseño responsivo

El diseño responsivo es un enfoque para diseñar una interfaz que cambia según el tamaño de la pantalla.

Existen varias formas de implementar el diseño responsivo. Una de las más comunes son las consultas @media, que aplican CSS a los elementos según las características de un dispositivo.

Por ejemplo, supongamos que deseas pasar de un diseño vertical a uno horizontal según la orientación. Establece las propiedades CSS en modo vertical de forma predeterminada:

.page-container {
    display: -webkit-box;
    display: flex;

    -webkit-box-orient: vertical;
    flex-direction: column;

    padding: 20px;
    box-sizing: border-box;
}

Para cambiar a un diseño horizontal, cambia la propiedad flex-direction según la orientación:

@media screen and (orientation: landscape) {
  .page-container.notification-opened {
    -webkit-box-orient: horizontal;
    flex-direction: row;
  }

  .page-container.notification-opened > .notification-arrow {
    margin-right: 20px;
  }
}

También puedes cambiar el diseño según el ancho de la pantalla.

Por ejemplo, ajustar el tamaño del ancho del botón del 100% a algo más pequeño a medida que aumenta el tamaño físico de la pantalla.

button {
  display: block;
  width: 100%;
  ...
}

@media screen and (min-width: 500px) {
  button {
    width: 60%;
  }
}

@media screen and (min-width: 750px) {
  button {
    width: 40%;
    max-width: 400px;
  }
}

Estos son cambios menores, pero, según tu IU, las consultas de contenido multimedia pueden ayudarte a realizar cambios mucho más grandes en la apariencia de tu aplicación y, al mismo tiempo, mantener el mismo código HTML.

Imágenes nítidas y claras

La variedad de tamaños y densidades de pantalla también presenta desafíos para las imágenes. Las imágenes más pequeñas requieren menos memoria y se cargan más rápido, pero se vuelven borrosas si las escalas.

A continuación, se incluyen algunas sugerencias y trucos para garantizar que tus imágenes se vean nítidas y claras en cualquier pantalla:

  • Usa CSS para efectos escalables.
  • Usa gráficos vectoriales.
  • Proporciona fotos de alta resolución.

Usa CSS para efectos escalables

Usa CSS siempre que puedas, en lugar de imágenes. Es posible que algunas combinaciones de propiedades CSS sean costosas de renderizar. Siempre prueba las combinaciones específicas que usas.

Obtén más información sobre el primer procesamiento de imagen con contenido (FCP), que mide el tiempo desde que el usuario navegó por primera vez a la página hasta que se renderiza en la pantalla cualquier parte del contenido de la página. "Contenido" se refiere al texto, las imágenes (incluidas las imágenes de fondo), los elementos <svg> y los elementos <canvas> que no sean de color blanco.

Usa gráficos vectoriales

Los gráficos vectoriales escalables (SVG) son una excelente manera de proporcionar una imagen escalable. En el caso de las imágenes que se adaptan bien a los gráficos vectoriales, SVG proporciona imágenes de alta calidad con tamaños de archivo muy pequeños.

Proporciona fotos de alta resolución

Usa una foto adecuada para un dispositivo de alta densidad de píxeles y escala la imagen con CSS. De esta manera, la imagen se puede renderizar en alta calidad en todos los dispositivos. Si usas una compresión alta (configuración de baja calidad) cuando generas la imagen, es posible que puedas obtener buenos resultados visuales con un tamaño de archivo razonable.

Este enfoque tiene algunas posibles desventajas: las imágenes muy comprimidas pueden mostrar algunos artefactos visuales, por lo que debes experimentar para determinar qué nivel de compresión consideras aceptable. Además, cambiar el tamaño de la imagen en CSS puede ser una operación costosa.

Si la compresión alta no es adecuada para tus necesidades, prueba el formato WebP, que proporciona una imagen de alta calidad con un tamaño de archivo relativamente pequeño. Recuerda proporcionar un resguardo para las versiones de Android en las que no se admite WebP.

Control detallado

En muchos casos, no puedes usar una sola imagen para todos los dispositivos. En este caso, puedes seleccionar diferentes imágenes según el tamaño y la densidad de la pantalla. Usa consultas de medios para seleccionar imágenes de fondo según el tamaño y la densidad de la pantalla.

Puedes usar JavaScript para controlar cómo se cargan las imágenes, pero esto agrega complejidad.

Consultas de medios y densidad de pantalla

Para seleccionar una imagen según la densidad de la pantalla, debes usar unidades dpi o dppx en tu consulta de contenido multimedia. La unidad dpi representa puntos por pulgada de CSS y dppx representa puntos por píxel de CSS.

En la siguiente tabla, puedes ver la relación entre dpi y dppx.

Proporción de píxeles del dispositivo Densidad de pantalla generalizada Puntos por pulgada CSS (dpi) Puntos por píxel de CSS (dppx)
1x MDPI 96dpi 1dppx
1.5 veces HDPI 144dpi 1.5dppx
2 XHDPI 192dpi 2dppx

Android define los buckets de densidad de pantalla generalizados y se usan en otros lugares para expresar la densidad de pantalla (por ejemplo, https://screensiz.es).

Imágenes de fondo

Puedes usar consultas de medios para asignar imágenes de fondo a los elementos. Por ejemplo, si tienes una imagen de logotipo con un tamaño de 256 × 256 píxeles en un dispositivo con una relación de píxeles de 1.0, puedes usar las siguientes reglas de CSS:

.welcome-header > h1 {
  flex: 1;

  width: 100%;

  max-height: 256px;
  max-width: 256px;

  background-image: url('../images/html5_256x256.png');
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
}

Para cambiarla por una imagen más grande en dispositivos con una relación de píxeles de 1.5 (hdpi) y 2.0 (xhdpi), puedes agregar las siguientes reglas:

@media screen and (min-resolution: 1.5dppx) {
  .welcome-header > h1{
    background-image: url('../images/html5_384x384.png');
  }
}

@media screen and (min-resolution: 2dppx) {
  .welcome-header > h1{
    background-image: url('../images/html5_512x512.png');
  }
}

Luego, puedes combinar esta técnica con otras consultas de contenido multimedia, como min-width, que es útil a la hora de tener en cuenta diferentes factores de forma.

@media screen and (min-resolution: 2dppx) {
  .welcome-header > h1{
    background-image: url('../images/html5_512x512.png');
  }
}

@media screen and (min-resolution: 2dppx) and (min-width: 1000px) {
  .welcome-header > h1{
    background-image: url('../images/html5_1024x1024.png');

    max-height: 512px;
    max-width: 512px;
  }
}

Es posible que notes que max-height y max-width están configurados en 512 px para una resolución de 2ddpx, con una imagen de 1,024 x 1,024 px. Esto se debe a que un "píxel" de CSS, en realidad, tiene en cuenta la relación de píxeles del dispositivo (512 px × 2 = 1,024 px).

¿Qué sucede con <img/>?

Actualmente, la Web no tiene una solución para esto. Hay algunas propuestas, pero no están disponibles en los navegadores actuales ni en WebView.

Mientras tanto, si generas tu DOM en JavaScript, puedes crear varios recursos de imagen en una estructura de directorio bien pensada:

images/
  mdpi/
    imagename.png
  hdpi/
    imagename.png
  xhdpi/
    imagename.png

Luego, usa la relación de píxeles para intentar extraer la imagen más adecuada:

function getDensityDirectoryName() {
  if(!window.devicePixelRatio) {
    return 'mdpi';
  }

  if(window.devicePixelRatio > 1.5) {
    return 'xhdpi';
  } else if(window.devicePixelRatio > 1.0) {
    return 'hdpi';
  }

  return 'mdpi';
}

Como alternativa, puedes alterar la URL base de la página para definir las URLs relativas de las imágenes.

<!doctype html>
<html class="no-js">
<head>
  <script>
    function getDensityDirectoryName() {
      if(!window.devicePixelRatio) {
          return 'mdpi';
      }

      if(window.devicePixelRatio > 1.5) {
          return 'xhdpi';
      } else if(window.devicePixelRatio > 1.0) {
          return 'hdpi';
      }

      return 'mdpi';
    }

    var baseUrl =
        'file:///android_asset/www/img-js-diff/ratiores/'+getDensityDirectoryName()+'/';
    document.write('<base href="'+baseUrl+'">');
  </script>

    ...
</head>
<body>
    ...
</body>
</html>

Este enfoque bloquea la carga de la página y fuerza el uso de rutas absolutas para todos los recursos, como imágenes, secuencias de comandos y archivos CSS, ya que la URL base apunta a un directorio específico de densidad.