精美像素风格的 WebView

发布时间:2014 年 2 月 28 日

您可以使用多种选项为 WebView 创建完美的界面。

设置视口元标记

视口元标记是需要添加到 Web 应用中最重要的标记。如果没有此标记,WebView 的行为可能会像您的网站是专为桌面浏览器设计的一样。这会导致网页的宽度更大(通常为 980px),并将其缩放以适应 WebView 宽度。在大多数情况下,这会导致页面显示一个小小的概览版本,用户需要平移和缩放才能实际阅读内容。

如果您希望网站的宽度为 WebView 宽度的 100%,请设置视口元标记:

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

将 width 设置为特殊值 device-width,以便更好地控制页面布局。

默认情况下,WebView 会将视口设置为“device-width”,而不是默认设置为桌面版视口。不过,为了实现可靠且可控的行为,最好添加视口元标记。

显示桌面版网站

在某些情况下,您可能需要显示不适用于移动设备的内容。例如,您可能会展示您无法控制的内容。在这种情况下,您可以强制 WebView 使用桌面大小的视口:

如果未设置这些方法未指定视口,WebView 会尝试根据内容大小设置视口宽度。

此外,您可能还需要使用布局算法 TEXT_AUTOSIZING,该算法会增大字体大小,以便在移动设备上更易于阅读。请参阅 setLayoutAlgorithm

使用自适应设计

自适应设计是一种设计界面的方法,可根据屏幕尺寸进行调整。

您可以通过多种方式实现响应式设计。最常见的一种是 @media 查询,它会根据设备的特性将 CSS 应用于元素。

例如,假设您希望根据屏幕方向从垂直布局切换到水平布局。将 CSS 属性设置为默认纵向:

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

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

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

如需切换到横向布局,请根据屏幕方向切换 flex-direction 属性:

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

您还可以根据屏幕宽度更改布局。

例如,随着实体屏幕尺寸变大,将按钮宽度的大小从 100% 调整为更小的值。

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

这些是细微的更改,但根据您的界面,媒体查询可以帮助您对应用的外观进行更大的更改,同时保持相同的 HTML。

清晰的图片

各种各样的屏幕尺寸和密度也给图片带来了挑战。图片越小,所需的内存就越少,加载速度就越快,但如果您放大图片,则会变得模糊。

下面列出了一些提示和技巧,可确保您的图片在任何屏幕上都清晰锐利:

  • 使用 CSS 实现可伸缩的效果。
  • 使用矢量图形。
  • 提供高分辨率照片。

使用 CSS 实现可伸缩的效果

尽可能使用 CSS,而不是图片。某些 CSS 属性组合的渲染成本可能很高。请务必测试您使用的具体组合。

详细了解首次内容渲染 (FCP),该指标衡量从用户首次导航到网页到网页任何一部分内容呈现在屏幕上的时间。“内容”是指文本、图片(包括背景图片)、<svg> 元素和非白色 <canvas> 元素。

使用矢量图形

可缩放矢量图形 (SVG) 是提供可缩放图片的绝佳方式。对于非常适合矢量图形的图片,SVG 可提供文件大小非常小的高品质图片。

提供高分辨率照片

使用适合高 DPI 设备的照片,并使用 CSS 缩放图片。这样,图片便可以在各种设备上以高画质呈现。如果您在生成图片时使用高压缩(低画质设置),则可能能够在文件大小合理的情况下获得良好的视觉效果。

这种方法有几个潜在的缺点:高度压缩的图片可能会显示一些视觉伪影,因此您需要进行实验,确定您可以接受的压缩级别。在 CSS 中调整图片大小是一项耗时操作。

如果高压缩不符合您的需求,请尝试使用 WebP 格式,这种格式可提供质量较高且文件大小相对较小的图片。请务必为不支持 WebP 的 Android 版本提供回退方案。

精细的控制

在许多情况下,您无法为所有设备使用单个映像。在这种情况下,您可以根据屏幕尺寸和密度选择不同的图片。使用媒体查询按屏幕尺寸和密度选择背景图片。

您可以使用 JavaScript 来控制图片的加载方式,但这会增加复杂性。

媒体查询和屏幕密度

如需根据屏幕密度选择图片,您需要在媒体查询中使用 dpidppx 单位。dpi 单位表示每 CSS 英寸的点数,dppx 表示每 CSS 像素的点数。

在下表中,您可以看到 dpidppx 之间的关系。

设备像素比 一般化屏幕密度 每 CSS 英寸的点数 (dpi) 每 CSS 像素的点数 (dppx)
1x MDPI 96dpi 1dppx
1.5 倍 HDPI 144dpi 1.5dppx
2 XHDPI 192dpi 2dppx

通用屏幕密度分桶由 Android 定义,用于在其他位置表示屏幕密度(例如 https://screensiz.es)。

背景图片

您可以使用媒体查询为元素分配背景图片。例如,如果您在像素比率为 1.0 的设备上有一个尺寸为 256 像素 x 256 像素的徽标图片,则可以使用以下 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;
}

如需在设备像素比为 1.5 (hdpi) 和 2.0 (xhdpi) 的设备上将此图片替换为较大的图片,您可以添加以下规则:

@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');
  }
}

然后,您可以将此方法与其他媒体查询(例如 min-width)合并,这在考虑不同外形规格时非常有用。

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

您可能会注意到,对于 2ddpx 分辨率,max-heightmax-width 均设置为 512 像素,而图片的大小为 1024 x 1024 像素。这是因为 CSS“像素”实际上会考虑设备像素比率(512 像素 * 2 = 1024 像素)。

<img/> 怎么样?

目前,网络上还没有针对此问题的解决方案。有一些提案,但当前的浏览器或 WebView 中不支持这些提案。

与此同时,如果您使用 JavaScript 生成 DOM,则可以在经过深思熟虑的目录结构中创建多个图片资源:

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

然后,使用像素比率尝试拉取最合适的图片:

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

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

  return 'mdpi';
}

或者,您也可以更改网页的基础网址,以定义图片的相对网址。

<!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>

由于基本网址指向特定密度的目录,因此此方法会阻止网页加载,并强制使用所有资源(例如图片、脚本和 CSS 文件)的绝对路径。