安卓和ios的输入框弹出键盘时,导致fixed或absolute定位的按钮顶上去的问题
遇到的问题
在移动端中input唤起键盘的时候,会导致底部被fixed或者absoluted的button被顶上去,解决的第一思路就是要监听到键盘弹起的事件,对此解决方案要分为ios和android两种情况。问题如图所示:
就是如上图一个很简单的textarea,下面的关闭是absolute的。部分代码如下:
HTML
<div class="textarea-wrapper">
<textarea placeholder="请填写您要展示的文字内容"
v-model="textContent"
></textarea>
<div class="submit">...</div>
</div>
<div class="close">
<button type="button" @click="close">
关 闭
</button>
</div>
CSS
.close {
position: absolute;
left: 0;
right: 0;
bottom: 0;
padding: 0 0 30px;
text-align: center;
button {
color: #fff;
background-color: ...;
width: 50%;
line-height: 40px;
}
}
解决方法
主要的原理是分别考虑focus事件和onresize 事件,在focus为true时,再去考虑onresize 导致的窗口高度是否发生变化。
这是因为对于android,输入框的弹起必然导致onresize 事件的发生,窗口高度是一定会变化的,但焦点并不一定和此完全相关,例如,输入框获取焦点后,收回键盘,焦点并不会随之撤出;
但ios上焦点和键盘弹出是绝对相关的关系,相反的,ios中键盘的弹起并不会触发onresize事件。同时,ios上键盘弹起也不会影响absolute定位。
因此,我们不仅要对textarea的focus和blur做触发方法,同时也要监听屏幕高度变化,判断是否调起了键盘。
对HTML的修改:
<textarea
placeholder="请填写您要展示的文字内容"
@focus="toggleTextareaFocus(true)"
@blur="toggleTextareaFocus(false)"
v-model="textContent"
></textarea>
<div class="close" :class="{'focus-text': focusText}">
<button type="button" @click="close">
关 闭
</button>
</div>
CSS
.close {
position: absolute;
...
&.focus-text{
opacity: 0;
}
button {
...
}
}
JS
const SCREEN_HEIGHT = Math.floor(window.innerHeight);
const IS_IOS = (() => {
let reg = /iphone|ipod|ipad|Macintosh/i;
return reg.test(navigator.userAgent.toLowerCase());
})();
mounted() {
// 当唤起键盘时 屏幕尺寸会发生改变 这里只针对安卓 苹果虚拟键盘调起的时候不触发屏幕变化事件
window.onresize = () => {
if (IS_IOS) {
return;
}
const resizeHeight = document.body.clientHeight;
// 当安卓端键盘调上来后document.body.clientHeight和window.innerHeight值一致
if (resizeHeight < SCREEN_HEIGHT) {
// 如果变化后的高度比之前小 代表虚拟键盘展开了 那么代表需要隐藏按钮
this.focusText = true;
} else {
// 如果变化后的高度>=之前 代表虚拟键盘关闭了 但是此时失焦与否不确定
this.focusText = false;
}
}
},
methods: {
toggleTextareaFocus(focus) {
if (IS_IOS) {
return;
}
this.focusText = focus;
},
}
这里需要添加失焦、聚焦时候都要有事件,并且要排除掉IOS,否则聚焦时候在IOS上会隐藏掉按钮。