随着科技的进步,移动端发展日新月异,到现在几乎是全面屏的天下,但市面上依然存在很多非全面屏的手机。
对于前端开发而言,做好对新型号和老型号手机的适配是毋庸置疑的,同时全面屏页意味着更多的差异
从大方向来讲ios和安卓系列手机的差异,小的来说,ios不同的版本,安卓不同的开发商机型都会存在其特有的显示规律,
首先以承载ios的iphone系列为例
iOS 11中采用了viewport-fit的meta标签作为适配方案;viewport-fit的默认值是auto
表头 | 表头 |
---|---|
auto | 默认:viewprot-fit:contain;页面内容显示在safe area内 |
cover | viewport-fit:cover,页面内容充满屏幕 |
在iOS 11+ 中的WebKit包含了一个新的CSS函数constant(),以及一组四个预定义的常量:safe-area-inset-left, safe-area-inset-right, safe-area-inset-top和 safe-area-inset-bottom
当合并一起使用时,允许样式引用每个方面的安全区域的大小。(必须要 viewport-fit=cover 才能生效)
padding-bottom: constant(safe-area-inset-bottom); /* 兼容 iOS < 11.2 */
padding-bottom: env(safe-area-inset-bottom); /* 兼容 iOS >= 11.2 */
之所以写了constant和env两种 是因为ios11.2版本以后constant废弃,env生效 写2种是兼容所有ios版本
顶部按钮
左部按钮
右部按钮
底部按钮
.area-style {
position: fixed;
height: 40px;
border-radius: 30px;
}
.button-style {
line-height: 40px;
font-size: 24px;
color: black;
}
.top-area {
.area-style;
top: 0;
width: 100%;
background-color: pink;
top: calc(constant(safe-area-inset-top) + 10px);
top: calc(env(safe-area-inset-top) + 10px);
}
.left-area {
.area-style;
width: 30%;
bottom: 100px;
left: 0;
background-color: grey;
left: calc(constant(safe-area-inset-left) + 0px);
left: calc(env(safe-area-inset-left) + 0px);
}
.right-area {
.area-style;
width: 30%;
bottom: 100px;
right: 0;
background-color: blue;
right: calc(constant(safe-area-inset-right) + 0px);
right: calc(env(safe-area-inset-right) + 0px);
}
.bottom-area {
.area-style;
width: 100%;
bottom: 0;
background-color: red;
bottom: calc(constant(safe-area-inset-bottom) + 10px);
bottom: calc(env(safe-area-inset-bottom) + 10px);
}
在iPhone8和iphone13效果如图所示:
竖屏:iphone13 && iphone12Pro && iphone8:
横屏:iphone13 && iphone12Pro && iphone8:
在横屏的时候安全区域的定义:但即使能够通过constant和env函数帮助解决安全区域问题,仍有不足之处:
左右按钮的相对边框位置发生了改变
那么怎么保证竖屏和横屏时的页面布局尽可能保持一致呢?官方在11.2版本之后 还增加了max() min() 去解决兼容横纵向切换时出现的问题 设置safe-area-inset-left左边距距离横向正常 恢复为纵向时,env(safe-area-inset-left)被解析为0px 左侧内容会紧贴屏幕所以使用如下方式做兼容
所以,我们可以对上面的左右按钮样式做出一点改造
.left-area {
position: fixed;
width: 30%;
bottom: 100px;
left: 0;
height: 40px;
border-radius: 30px;
background-color: grey;
left: max(calc(constant(safe-area-inset-left) + 0px), 6%);
left: max(calc(env(safe-area-inset-left) + 0px), 6%);
}
.right-area {
position: fixed;
width: 30%;
bottom: 100px;
right: 0;
height: 40px;
border-radius: 30px;
background-color: blue;
right: max(calc(constant(safe-area-inset-right) + 0px), 6%);
right: max(calc(env(safe-area-inset-right) + 0px), 6%);
}
这样竖屏的时候就会变成这样,风格和横屏的时候就较为一致了
软键盘d出的适配首先ios在点击input框的时候,为了防止页面被自动放大,我们需要增加 maximum-scale=1.0 或者 user-scalable=no属性禁止屏幕被放大
当我们统一采用fixed形式的布局后
底部按钮
.input-area {
position: fixed;
width: 80%;
bottom: 200px;
left: 10%;
height: 20px;
bottom: calc(constant(safe-area-inset-bottom) + 200px);
bottom: calc(env(safe-area-inset-bottom) + 200px);
}
ios:
安卓:
当移动端软键盘被唤起后,ios的屏幕会被整个顶起,肉眼可见灰色区域和”顶部按钮“被顶到看不到的上方,但软键盘遮住的主屏幕是可以通过滑动看到灰色区域和”顶部按钮“,
也就是说ios中的任何布局,包含fixed也只是针对初始尺寸屏幕的fixed,再软键盘被唤起后,所谓的fixed变成了static的效果,页面所有元素的相对位置都被固定住,
而安卓的fixed是针对可见范围内的fixed,除fixed之外的元素不会被影响布局,即页面所有元素的相对位置会发生改变。
ios:是可视窗口向上顶上去了。
安卓:是可视窗口缩小了。
这样虽然会导致差异,但终究都是能正常显示的。
那如果我们尝试将input的position设置为static呢?.input-area {
position: static;
width: 40%;
left: 30%;
height: 20px;
}
ios && 安卓:
在一些特殊情况下,如页面内容区域的底部存在输入框,同时页面底部有固定的按钮,在唤起软键盘后
ios还是原来的样子,static的输入框相对于fixed的按钮相对位置并没有变化,但安卓会以input框的下边界为输入框的上边界,紧贴着显示
这个时候ios采用的显示方式效果是优于安卓的,页面的布局没有发生任何变化,输入框还是清晰的展示出来,
但安卓却出现了按钮遮盖输入框的情况。真实的业务开发中其实经常会遇到底部固定按钮,搭配输入框在可视区域相对底部的情况
但解决这个问题也很容易:不要让input位于内容区域的最底部,给input下方增加一些安全距离就行,在d起软键盘后,不管是ios还是安卓都会将input朝着可视化区域的中心位置去安置。
这个问题发生的原因就是,安卓机制处理input框位置的时候由于下方没有内容,只能紧贴软键盘显示,而原先的底部fixed就会覆盖底部的显示
关于软键盘的控制如果想要达到更细粒度,就需要对js进行控制,但ios和安卓对监听软键盘d起和关闭的机制是不一样的
ios中软键盘的d起和关闭会触发input框的focusin和focusout事件,而安卓中软键盘的关闭并不会引发失焦事件,可以通过窗口的resize事件中引发的offsetHeight和windowHeight相对值变化来判断软键盘状态
const [popUp, changePop] = useState(false);
const isIOS = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
if (isIOS) {
document.body.addEventListener("focusin", () => {
// 软键盘d起事件
changePop(true);
});
document.body.addEventListener("focusout", () => {
// 软键盘关闭事件
changePop(false);
});
} else {
const orignHeight =
document.documentElement.clientHeight || document.body.clientHeight;
window.onresize = () => {
const resizeHeight =
document.documentElement.clientHeight || document.body.clientHeight;
changePop(orignHeight - resizeHeight > 140);
};
}
{popUp ? "软键盘--d起" : "软键盘--关闭"}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)