前言:H5 有时底部按钮是固定定位,当页面上面需要用到输入内容时,会弹起软键盘,然后把底部固定的按钮也弹起来了,我们希望弹起软键盘时,底部的固定定位按钮隐藏,这里就需要对移动端软键盘弹起收起进行监听。
1. Android端
const [hideBottom, setHideBottom] = useState<boolean>(false);
useEffect(() => {
const originalHeight = document.documentElement.clientHeight || document.body.clientHeight;
window.addEventListener('resize', () => {
const resizeHeight = document.documentElement.clientHeight || document.body.clientHeight;
if (resizeHeight - 0 < originalHeight - 0) {
setHideBottom(true);
} else {
setHideBottom(false);
}
});
}, []);
OR
const [hideBottom, setHideBottom] = useState<boolean>(false);
useEffect(() => {
const originalHeight = document.documentElement.clientHeight || document.body.clientHeight;
window.onresize = () => {
const resizeHeight = document.documentElement.clientHeight || document.body.clientHeight;
if (resizeHeight - 0 < originalHeight - 0) {
setHideBottom(true);
} else {
setHideBottom(false);
}
};
}, []);
2. IOS端
const [hideBottom, setHideBottom] = useState<boolean>(false);
useEffect(() => {
document.body.addEventListener('focusin', () => {
setHideBottom(true);
});
document.body.addEventListener('focusout', () => {
setHideBottom(false);
});
}, []);
3. 融合终极办法
export const monitorSoftKeyboard = callback => {
const originalHeight = document.documentElement.clientHeight || document.body.clientHeight;
window.addEventListener('resize', () => {
const resizeHeight = document.documentElement.clientHeight || document.body.clientHeight;
if (resizeHeight - 0 < originalHeight - 0) {
callback(true);
} else {
callback(false);
}
});
document.body.addEventListener('focusin', () => {
callback(true);
});
document.body.addEventListener('focusout', () => {
callback(false);
});
};
const [hideBottom, setHideBottom] = useState<boolean>(false);
useEffect(() => {
monitorSoftKeyboard(isUp => {
if (isUp) {
setHideBottom(true);
} else {
setHideBottom(false);
}
});
}, []);
解释
- 在android中软键盘弹起或收起时,会改变window的高度,因此监听window的onresize事件;但是 ios 中软键盘的弹起收起并不触发 window.onresize 事件;
- 在 ios 中软键盘弹起时,仅会引起 scrollTop 值改变,但是我们可以通过输入框的获取焦点情况来做判断,但也只能在 ios 中采用这个方案,因为在 android 中存在主动收起键盘后,但输入框并没有失焦,而ios中键盘收起后就会失焦
- 另外,focusin和focusout支持冒泡,对应focus和blur, 使用focusin和focusout的原因是focusin和focusout可以冒泡,focus和blur不会冒泡,这样就可以使用事件代理,处理多个输入框存在的情况。