原始文章:https://developer.chrome.com/multidevice/webview/pixelperfect
您可以使用许多选项来创建完美的UI,本文将概述一般移动网络的一些最佳做法,然后介绍可用于混合应用程序的一些具体技巧。
Viewport
viewport meta标签是最重要的标记你需要添加到您的web应用程序。没有它,WebView可能认为你的网站是专为桌面浏览器。这将导致您的web页面被赋予更大的宽度(通常是980 px)和尺度适应WebView的宽度。在大多数情况下,结果是产生一个小页面,要求用户的平移和缩放工具实际阅读内容,像左边的图片。
如果你想要你的网站的宽度是100%的WebView的宽度,正如右边显示的,你需要设置viewport元标签:
<meta name="viewport" content="width=device-width, initial-scale=1">
将宽度设置为特殊值设备宽度可以让您更好地控制页面布局。
默认情况下,WebView将把viewport设置为设备宽度,而不是默认设置为桌面viewport。但是,为了可靠和受控的行为,最好将viewport元标记包含进来。
桌面网站
在某些情况下,你可能需要显示那些不是为移动设备而设计的内容——例如,如果你显示的内容是你无法控制的。在这种情况下,您需要强制WebView使用桌面大小的viewport:
setLoadWithOverviewMode(true)
如果这些方法没有设置,并且没有指定viewport,WebView将尝试根据内容大小设置viewport宽度。
除了这样做,你可能想要使用Android 4.4中引入的新的布局算法text_autosize,它增加了字体大小,使它在移动设备上更具可读性。参见setLayoutAlgorithm。
响应设计
响应式设计是指根据屏幕大小的大小来改变UI的概念。在这里,我们将看到一些简单的例子,说明如何调整UI和图像,但是如果您想深入了解其他主题,那么这篇关于HTML5Rocks的文章是一个很好的参考点。
您想要使用的主要CSS特性之一是媒体查询。
媒体查询是一种将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;
}
}
这些是微小的变化,但根据您的UI,媒体查询可以帮助您对应用程序的外观进行更大的更改,同时保持相同的HTML。
提示:当一个组件开始看不到的时候,尝试根据宽度更改UI,而不是专注于设备大小。 通过这样做,您的应用程序将在一系列设备上看起来不错,而不仅仅是您测试的设备。 这样做的一个简单方法是浏览器窗口的大小。 但请记住,实际设备的屏幕密度与显示器的屏幕密度不同,因此始终对各种设备进行测试。
有关移动设备设计的更多信息,请参阅HTML5Rocks。
Images
屏幕尺寸和密度的多样性也给图像带来挑战。 较小的图像需要更少的内存并且加载速度更快,但如果将其缩放,则会模糊。
下面的图片显示了当你将一个低密度图像放大到一个高密度的屏幕时发生的模糊,与一个适当大小的图像的清晰显示相比。
这里有一些提示和技巧,以确保您的图像在任何屏幕上看起来清晰和明确:
使用CSS可扩展的效果。
使用矢量图形。
提供高分辨率照片。
使用CSS可扩展的效果
使用CSS3,你可以在边界上,投下阴影,边界半径,等等,而不是图像。这些功能可以很容易地伸缩。然而,一些CSS属性的组合渲染可能会很开销很大,所以您应该经常测试您所使用的特定组合。(关于快速和慢的CSS属性的一些示例数据,请参见:CSS Paint Times and Page Render Weight on HTML5Rocks)。
使用矢量图形
可缩放矢量图形(SVG)是提供可扩展版本的图像的好方法。 对于非常适合矢量图形的图像,SVG提供了非常小的文件大小的高质量图像。 有关更多信息,请参阅Splash Vector Graphics on your Responsive Site on HTML5Rocks。
提供高分辨率照片
使用适合于high-DPI设备的版本,并使用CSS缩放图像。通过这种方式,图像在设备上具有很高的质量。如果你在生成图像时使用高压缩(低质量的设置),你可以使用一个合理的文件大小来实现良好的视觉效果。
这种方法很简单,但有一些潜在的缺点:高度压缩的图像可能会显示一些视觉工件,因此您需要进行实验来确定您可以接受的压缩级别。 并且在CSS中调整图像大小可能是一项开销很大的操作。
如果高压缩不适合您的需要,试试WebP格式,它提供了一个高质量的图像,文件大小相对较小。详情请参阅官方WebP网站。别忘了,你需要为那些不支持WebP的老版本的Android提供一个退路。
细粒度控制
在许多情况下,您不能对所有设备使用一个图像。 在这种情况下,您可以根据屏幕尺寸和密度选择不同的图像。 您可以使用媒体查询通过屏幕大小和密度来选择背景图像。 您还可以使用JavaScript来控制图像的加载方式。
媒体查询和屏幕密度
要根据屏幕密度选择图像,您需要在媒体查询中使用dpi或dppx单位。 dpi单位表示每个CSS英寸的点数,而dppx表示每个CSS像素的点数。
看下面的表格,你可以看到dpi和dppx之间的关系。 1dppx相当于96dpi,2dppx == 192dpi == 2 x 96dpi等等。
设备像素比 | 广义屏幕密度 | 每英寸点数(dpi) | 每个CSS像素点数(dppx) |
---|---|---|---|
1x | MDPI | 96dpi | 1dppx |
1.5x | HDPI | 144dpi | 1.5dppx |
2 | XHDPI | 192dpi | 2dppx |
广义屏幕密度桶由Android本机平台定义,并在其他地方用于表示屏幕密度(例如http://screensiz.es)。
背景图像
您可以使用媒体查询将背景图像分配给元素。例如,如果你有一个有256px x256px大小的标志图像,在一个像素比为1.0的设备上,你可以使用以下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;
}
}
您可能注意到,max - height和max - width设置为512px的2ddpx分辨率,图像为1024x1024px。这是因为CSS“像素”实际上考虑到设备像素比(512px * 2 = 1024px)。
< 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';
}
在JS中实现上述的替代方法是更改页面的基本URL以定义图像的相对URL。
<!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文件,链接等,因为基本URL指向密度特定的目录。