ios与安卓底部按钮与输入框的兼容性

ios与安卓底部按钮与输入框的兼容性,第1张

全面屏显示的适配

随着科技的进步,移动端发展日新月异,到现在几乎是全面屏的天下,但市面上依然存在很多非全面屏的手机。
对于前端开发而言,做好对新型号和老型号手机的适配是毋庸置疑的,同时全面屏页意味着更多的差异

从大方向来讲ios安卓系列手机的差异,小的来说,ios不同的版本,安卓不同的开发商机型都会存在其特有的显示规律,
首先以承载ios的iphone系列为例

iPhoneX的适配

iOS 11中采用了viewport-fit的meta标签作为适配方案;viewport-fit的默认值是auto

表头表头
auto默认:viewprot-fit:contain;页面内容显示在safe area内
coverviewport-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起" : "软键盘--关闭"}
  

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/996641.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存