背景介绍
我们公司的APP是通过安卓写的壳子,里面嵌套了前端开发的Vue页面或者H5页面。H5或Vue再去调用android或者IOS原生写的的方法。之前我接手的部分业务,为保证功能完整性,入口也需要使用H5实现,当时遇到了一些问题,其中包括布局适配问题。 本篇文章共2226字,阅读大概需要8分钟
核心:适配问题
说到布局,首先要提出来的就是viewport,哪viewport是什么?我们为什么需要使用它?
一、viewport
基本概念:viewport
指视口,浏览器上(或者是手机app的webview)的显示网页的区域。
PC端的视口是浏览器窗口区域,而移动端的则存在三个不同的视口以及meta标签:
- layout viewport:布局视口
- visual viewport:视觉视口(浏览器可视区域)
- ideal viewport:理想视口
- Meta viewport:meta标签
接下来分别介绍一下这四个概念:
layout viewport:布局视口
在PC端的网页的layout viewport
即浏览器页面显示的整个区域,也可以理解成网页的绘制区域
。而在移动端由于其屏幕较小,无法全部显示PC端页面的全部内容,所以默认情况下,移动端会指定一个大于其浏览器显示区域layout viewport。
visual viewport:视觉视口(浏览器可视区域)
这里我们使用两幅图来进行区分一下:
layout viewport:
visual viewport:
ideal viewport:理想视口
理想视口,即页面绘制区域可以完美适配设备宽度的视口大小
,不需要出现滚动条即可正常查看网站的所有内容,且文字图片清晰。这也是我们为什么需要使用viewport的原因。
Meta viewport
<meta>
元素表示那些不能由其它HTML
元相关元素之一表示的任何元数据信息,它可以告诉浏览器如何解析页面。
我们可以借助<meta>
元素的viewport
来帮助我们设置视口、缩放等,从而让移动端得到更好的展示效果
<meta name="viewport" content="width=device-width; initial-scale=1; maximum-scale=1; minimum-scale=1; user-scalable=no;">
viewport
属性含义:
Value | 可能值 | 描述 |
---|---|---|
width | 正整数或device-width | 以pixels (像素)为单位, 定义布局视口的宽度。 |
height | 正整数或device-height | 以pixels (像素)为单位, 定义布局视口的高度。 |
initial-scale | 0.0 - 10.0 | 定义页面初始缩放比率。 |
minimum-scale | 0.0 - 10.0 | 定义缩放的最小值;必须小于或等于maximum-scale 的值。 |
maximum-scale | 0.0 - 10.0 | 定义缩放的最大值;必须大于或等于minimum-scale 的值。 |
user-scalable | 一个布尔值(yes 或者no ) | 如果设置为 no ,用户将不能放大或缩小网页。默认值为 yes。 |
二、移动适配解决方案
移动布局分式有很多种,这里简单介绍3种布局方式:
flex弹性布局(最常用)
介绍:采用 Flex 布局的元素,称为 Flex Container
。它的所有子元素自动成为容器成员,称为Flex Item
。最大的作用就是:通过给父亲添加flex属性,从来控制内部项目的位置及排序方式。
优点方面:
- 使用方便,根据flex规则很容易达到一定的布局效果
缺点方面:
- 浏览器兼容性比较差,只能兼容ie9及以上
流式布局(百分比布局)
介绍:页面元素的宽度会根据屏幕分辨率自动进行适配。这种布局可以保证当你的屏幕分辨率发生改变也不会发送混乱,会一直保持适配。
优点方面:
- 宽度自适应,在不同的分辨率下都能达到适配
缺点方面:
- 百分比的值不好计算
- 需要确定父级的大小,因为要根据父级的大小进行计算
- 各个属性中如果使用百分比,相对父元素的属性并不是唯一的
- 高度不好设置,一般需要固定高度
css3的媒体查询
@media screen and (max-width: 320px){
....适配小屏幕的css样式
}
@media screen and (max-width: 375px){
....适配普通屏幕的css样式
}
@media screen and (max-width: 414px){
....适配大屏幕的css样式
}
优点方面
:
- 方法简单,只需修改css文件
- 调整屏幕宽度时不用刷新页面就可以响应页面布局
缺点方面
:
- 代码量大,不方便维护
- 不能够完全适配所有的屏幕尺寸,需要编写多套css样式
思考(1px问题):
物理像素:
指的是设备屏幕上的像素点个数,比如苹果6是屏幕尺寸为4.7英寸
,分辨率为1334x750
像素,那么水平方向上有750个像素点
,竖直方向上有1334个像素点
。
CSS像素:
在我们去写CSS
时,我们用到最多的单位是px
,指的就是CSS像素
,当页面缩放比例为100%
时,一个CSS像素
等于一个设备独立像素。
但是CSS像素
是很容易被改变的,当用户对浏览器进行了放大,CSS像素
会被放大,这时一个CSS像素
会跨越更多的物理像素。
页面的缩放系数 = CSS像素 / 设备独立像素
。
在我们了解了以上之后,这里我抛出一个问题,基本上前端开发都会遇到的问题 图片模糊
,当时刚参加工作时,遇到了这个问题,然后查阅了资料之后才算是搞清楚原理。
图片模糊产生原因
我们平时使用的图片大多数都是PNG、JPG之类的,学过PS的人都知道,这些图都是通过一个个像素点构成的,每一个像素都有具体的位值和颜色值(像素值
),在开发中,位图的每一个像素应该去对应上设备的物理像素,对应上之后,才可以达到最佳效果,当然就不会产生图片迷糊这个问题。而在设备像素比 > 1
的屏幕上,1个位图像素对应于多个个物理像素
,由于单个位图像素不可以再进一步分割,所以只能就近取色,导致图片看起来比较模糊。
图片模糊解决方案
解决方案其实也很简单。我们只要让一个屏幕像素来渲染一个图片像素,所以,针对不同设备像素比
的屏幕,我们需要展示不同分辨率的图片。
如:在设备像素比=2
的屏幕上展示两倍图(@2x)
,在设备像素比=3
的屏幕上展示三倍图(@3x)
。
开发中遇到的布局问题:
场景一: APP原生功能页中,预留空白窗口,然后窗口中加载H5入口资源。
解决方案:
H5在组件加载完毕后,offsetHeight 获取当前组件高度,与APP通信告知H5入口组件的高度,APP拿到此高度后,设定适宜的窗口大小以容纳内嵌的H5入口组件
预知条件:H5调用方法时Android与iOS不同
H5 调用
Android:window.app.funName(data)
H5 调用 iOS: window.webkit.messageHandlers.app.postMessage({cmd: 'funName',data:data});
/**
* updateViewSize 为H5调用与APP协商的方法名
* entranceHeight 为H5的入口组件高度
*/
<template>
<div class="entrance" ref="appHeight"></div>
</template>
<script>
// 当前组件的高度
this.entranceHeight= this.$refs.appHeight.offsetHeight;
//通知APP,当前组件的高度
this.isAndroid ? window.app.updateViewSize(this.entranceHeight) : window.webkit.messageHandlers.app.postMessage({
cmd: 'updateViewSize',
data: this.entranceHeight});
});
</script>
场景二:当组件内容可变或动态获取,造成组件高度首次获取不准确
- 背景: 文案为后端返回,且有时切换语言造成换行,导致高度变化
解决方案:
- H5与APP通信告知高度的时机,添加在mounted即可
- 为了准确,最好watch服务端返回的文案数据,数据变化则等DOM更新完就通信
watch: {
/**
* 监听数据变化,DOM更新后及时通知APP最新高度,调整窗口
* 接口返回数据后,文案可能换行导致窗口高度发生改变
*/
someData() {
this.$nextTick(()=>{
// 当前组件的高度
this.entranceHeight= this.$refs.appHeight.offsetHeight;
//通知APP,当前组件的高度
this.isAndroid ? window.app.updateViewSize(this.entranceHeight) : window.webkit.messageHandlers.app.postMessage({
cmd: 'updateViewSize',
data: this.entranceHeight});
});
}
},
结尾
以上就是对布局适配
的理解和认识,总结的不足之处和理解不对的地方,欢迎指出讨论。感谢阅读!