关于H5在移动端弹出下拉选项时遮挡输入框的问题

2021-10-26 18:03:14 浏览数 (1)

背景

在最近的一个Hybrid App项目中,我实现的H5有以下两个需求:

  1. 使用quill.js实现富文本编辑器,但是,工具栏需要固定定位到底部,当输入法弹出时,工具栏需要悬浮在输入法键盘之上,如下图所示:
  1. 就是一个正常的表单,除了有文本输入,还有下拉选项,当下拉选项弹出时不能遮挡住聚焦的输入框,如下图所示,当点击左图的Complex Labels时,弹出下拉选项,下拉选项遮挡住了Complex Labels,产品要求的效果是:当下拉选项弹出时不能遮挡住当前聚焦的表单项,也就是Complex labels

quill.js工具栏定位问题

工具栏使用的是fixed定位,css如下所示:

代码语言:javascript复制
#ql-toolbar {
    position: fixed;
    bottom: 10px;
    left: 0;
    right: 0;
    z-index: 200; 
}
复制代码

fixed定位的元素是相对于屏幕视口(viewport)进行定位的,当H5嵌入到app的webview中进行展示时,可以理解为:fixed是相对于webview进行定位的。

当光标聚焦到编辑区输入文字时,系统级的输入法键盘弹出,此时,键盘的弹出对webview的高度会有一定的影响,而android和ios对webview的处理有所不同,简单的说就是:

  • android上:在下图中,键盘未弹出时,webview的高度 = 左图蓝色框的高度,当键盘弹出时,webview的高度 = 右图蓝色框的高度 - 红色框键盘的高度,也就是说webview的高度为绿色框的高度
  • ios上:webview的高度不会随着键盘的弹出而发生改变,始终是左图蓝色框的高度

综上,当工具栏使用fixed来定位时,在android上,当键盘弹出时webview的高度会减小,所以工具栏会悬浮在键盘之上,也就是说,在android上这么实现是符合需求的。但是,ios不会改变webview的高度,因此,当键盘弹出时,工具栏始终位于屏幕底部,从而被键盘遮挡,如此就不符合需求,所以,需要针对ios做特别处理

ios上的解决方案

有以下三种解决方案:

  1. 改设计: 将工具栏放在顶部,这样改动成本最小,兼容性最好,如果能说服产品,那么推荐这种方式
  2. 在ios app端,当键盘弹出时,配置webview的高度为屏幕高度 - 键盘高度,也就是与android保持一致的处理方式,这种方式不推荐使用,第一个原因是因为这么处理后相当于是改变了ios默认的处理机制,当H5放到其他ios app中使用时,还是会出现同样的遮挡问题;第二个原因是将H5的业务与端的强耦合在一起
  3. 在ios app端,当键盘弹出时,通过事件告知H5键盘的高度,然后H5根据webview的高度和键盘的高度动态的计算工具栏的位置,将其定位到键盘之上。当H5的页面只需要在我们的app端内使用,不需要兼容其他app时是可行的,如果需要兼容其他app则还是不可行,因为其他app并不会通过事件告知我们键盘的高度

总的来说这个问题并没有特别好的处理方式,或多或少都会存在一定问题,最终,我们确定的方案是由端来实现富文本编辑器,H5来实现编辑后的预览页面

下拉选项遮挡输入框的问题

对于文本输入框之所以不会遮挡,是因为文本输入框进行输入时,弹出的是系统级的输入法键盘,所以不会遮挡。但是对于下拉选项而言,弹出框的下拉选项是我们自己实现的,也就不是系统级的,所以,系统不会对其进行处理,如:将聚焦的输入框推动到可视范围之内,因此,会导致遮挡问题。

对于这个问题的解决需要分为以下几步:

  1. 如果滚动区的高度小于屏幕的高度,说明需要在底部填充空元素div来将页面撑开,产生垂直滚动条,以便将输入框顶上去,这个div的高度为弹出框的高度,暂定为popH,对于这种情况,到这一步即可解决遮挡的问题
  2. 如果滚动区的高度大于屏幕的高度,则需要按照如下流程进行处理:

源码 效果如下:

  1. 滚动区小于屏幕高度
  1. 滚动区的高度与屏幕高度相当
  1. 滚动区高度大于屏幕高度

0 人点赞