Date: 2022-04-15
在开发移动端的时候,我们可能需要识别键盘是否弹窗,然后处理一些特殊逻辑,那么如何识别该状态呢?
我们可能很容易想到监听输入框的 focus
和 blur
事件,然后部分安卓键盘右上角有收起操作,收起的时候并不会执行 blur
事件,输入框光标仍然在,导致我们无法精准的识别。
既然通过 focus
、blur
无法识别,那么我们很容易想到监听 resize
的触发,分析 iOS
和 Android
激活时的样式
当页面没有设置100%高度时,可以看到 iOS
、Android
激活键盘时,键盘会盖在页面的上方。
当页面设置100%高度,使用flex布局,header顶部固定,footer底部固定,中间区域滚动时,可以看到 iOS
键盘仍然时盖在上面,而 Android
激活键盘则会将页面往上顶。
Android
激活键盘会会触发 resize
,而 iOS
当输入框不在顶部时会触发 scroll
事件,在顶部时不会触发 scroll
事件,我们使用 focusin
和 focusout
来捕获。
使用Vue的方式如下:
<template>
<div class="keyboard-view">
<header>header</header>
<main>
<div class="empty-box"></div>
<br>
<div>
<input type="text" placeholder="请输入">
</div>
<br>
<div class="empty-box"></div>
</main>
<footer>footer</footer>
<div class="fixed-mask">
键盘state: {{ state }}
</div>
</div>
</template>
<script>
export default {
name: 'KeyboardVisible',
data () {
return {
state: '失焦',
docHeight: document.documentElement.clientHeight
}
},
mounted () {
this.keyboardShowListener()
},
methods: {
keyboardShowListener () {
let self = this
// 全局监听激活
function focusInFn () {
self.state = '激活'
self.keyboardShowFn()
}
// 全局监听失焦
function focusOutFn () {
self.state = '失焦'
self.keyboardHideFn()
}
// 监听iOS(当输入框在页面非顶部区域时都会触发)
function scrollFn () {
let scrollTop = document.documentElement.scrollTop || document.body.scrollTop
if (scrollTop == 0) {
self.state = '失焦'
self.keyboardHideFn()
} else {
self.state = '激活'
self.keyboardShowFn()
}
}
// 监听安卓
function resizeFn () {
let docHeight = document.documentElement.clientHeight
if (docHeight == self.docHeight) {
self.state = '失焦'
self.keyboardHideFn()
} else {
self.state = '激活'
self.keyboardShowFn()
}
}
document.body.addEventListener('focusin', focusInFn, false)
document.body.addEventListener('focusout', focusOutFn, false)
document.addEventListener('scroll', scrollFn, false)
window.addEventListener('resize', resizeFn, false)
this.$once('hook:beforeDestroy', function () {
document.body.removeEventListener('focusin', focusInFn, false)
document.body.removeEventListener('focusout', focusOutFn, false)
document.removeEventListener('scroll', scrollFn, false)
window.removeEventListener('resize', resizeFn, false)
})
},
keyboardShowFn () {
// alert('keyboardShowFn')
},
keyboardHideFn () {
// alert('keyboardHideFn')
}
}
}
</script>
<style lang="scss" scoped>
.keyboard-view{
height: 100%;
display: flex;
flex-direction: column;
header{
height: 40px;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
display: flex;
justify-content: center;
align-items: center;
}
footer{
height: 40px;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
display: flex;
justify-content: center;
align-items: center;
}
main{
padding: 16px;
flex: 1;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
input{
width: 100%;
height: 40px;
border: 1px solid #ccc;
padding: 10px;
box-sizing: border-box;
}
.empty-box{
height: 500px;
background-color:#ccc;
}
.fixed-mask{
width: 100px;
background-color: rgba(0, 0, 0, 0.5);
position: fixed;
right: 0;
top: 300px;
color: #fff;
padding: 5px;
font-size: 12px;
}
}
</style>