兼容移动端ios,安卓,web端底部软键盘弹出,输入框被遮挡问题

ops/2025/3/7 5:35:37/

思路:

1.监听键盘高度的变化
要监听键盘高度的变化,我们得先看看在键盘展开或收起的时候,分别会触发哪些浏览器事件:

  • iOS 和部分 Android 浏览器 展开:键盘展示时会依次触发 visualViewport resize -> focusin
    -> visualViewport scroll,部分情况下手动调用 input.focus 不触发 focusin 收起:键盘收起时会依次触发 visualViewport resize -> focusout -> visualViewport scroll

    -其他 Android 浏览器 展开:键盘展示的时候会触发一段连续的 window resize,约过 200 毫秒稳定
    收起:键盘收起的时候会触发一段连续的 window resize,约过 200 毫秒稳定,但是部分手机上有些异常的 case:键盘收起时viewport 会先变小,然后变大,最后再变小

if (window.visualViewport) {window.visualViewport?.addEventListener("resize", listener);window.visualViewport?.addEventListener("scroll", listener);
} else {window.addEventListener("resize", listener);
}
​
window.addEventListener("focusin", listener);
window.addEventListener("focusout", listener);

2.获取「键盘顶部距离视口顶部的高度」
键盘顶部距离视口顶部的高度 = 视口当前的高度 + 视口滚动上去高度
3.设置 input 的位置
键盘距离页面顶部高度」再减去「元素高度」,从而获得「当前元素的位移」

代码

import EventEmitter from "eventemitter3";// 默认屏幕高度
const DEFAULT_HEIGHT = window.innerHeight;
const MIN_KEYBOARD_HEIGHT = 200;export const KeyboardEvent = {Show: "keyboardShow",Hide: "keyboardHide",PositionChange: "keyboardPositionChange",
};class KeyboardObserver extends EventEmitter {constructor() {super();this.inited = false;this.lastWinHeight = DEFAULT_HEIGHT;this.canChangeStatus = true;this._unbind = () => { };}// 键盘初始化init() {if (this.inited) {return;}const listener = () => this.adjustPos();if (window.visualViewport) {window.visualViewport.addEventListener("resize", listener);window.visualViewport.addEventListener("scroll", listener);} else {window.addEventListener("resize", listener);}window.addEventListener("focusin", listener);window.addEventListener("focusout", listener);this._unbind = () => {if (window.visualViewport) {window.visualViewport.removeEventListener("resize", listener);window.visualViewport.removeEventListener("scroll", listener);} else {window.removeEventListener("resize", listener);}window.removeEventListener("focusin", listener);window.removeEventListener("focusout", listener);};this.inited = true;}unbind() {this.inited = false;this._unbind();}// 调整元素位置adjustPos() {// 获取当前视口高度const height = window.visualViewport? window.visualViewport.height: window.innerHeight;// 获取键盘高度const keyboardHeight = DEFAULT_HEIGHT - height;// 获取键盘顶部距离视口顶部的距离const top = height + (window.visualViewport?.pageTop || 0);this.emit(KeyboardEvent.PositionChange, { top });const diffHeight = height - this.lastWinHeight;this.lastWinHeight = height;// 如果高度减少,且减少高度大于 200,则视为键盘弹起if (diffHeight < 0 && keyboardHeight > MIN_KEYBOARD_HEIGHT) {this.onKeyboardShow({ height: keyboardHeight, top });} else if (diffHeight > 0) {this.onKeyboardHide({ height: keyboardHeight, top });}}onKeyboardShow(keyboardInfo) {if (this.canChangeStatus) {this.emit(KeyboardEvent.Show, keyboardInfo);this.setCanChangeStatus();}}onKeyboardHide(keyboardInfo) {if (this.canChangeStatus) {this.emit(KeyboardEvent.Hide, keyboardInfo);this.setCanChangeStatus();}}setCanChangeStatus() {this.canChangeStatus = false;const timer = setTimeout(() => {clearTimeout(timer);this.canChangeStatus = true;}, 200);}
}const keyboardObserver = new KeyboardObserver();export default keyboardObserver;

组件

<template><div><button @click="focusInput">点击我</button><!-- <div>{{ statusText }}</div> --><inputref="elRef"class="block":style="{ transform: `translateY(${top}px)` }"/></div>
</template><script>
import keyboardObserver, { KeyboardEvent } from "./keyboard";export default {name: 'App',data() {return {// statusText: '',top: window.innerHeight,};},created() {this.initKeyboardObserver();},beforeDestroy() {keyboardObserver.unbind();},methods: {initKeyboardObserver() {keyboardObserver.init();keyboardObserver.on(KeyboardEvent.PositionChange, this.onPositionChange);// keyboardObserver.on(KeyboardEvent.Show, this.onKeyboardShow);// keyboardObserver.on(KeyboardEvent.Hide, this.onKeyboardHide);},onPositionChange({ top }) {this.top = top - this.$refs.elRef.clientHeight;},// onKeyboardShow() {//   this.statusText = 'show';// },// onKeyboardHide() {//   this.statusText = 'hide';// },focusInput() {this.$refs.elRef.focus();},},
};
</script><style>
html,
body {margin: 0;padding: 0;height: 100%;width: 100%;
}#app {display: flex;align-items: center;justify-content: center;height: 100%;width: 100%;
}.block {position: fixed;top: 0;left: 0;width: 100%;height: 50px;display: flex;align-items: center;justify-content: center;transition: 0.2s all;background-color: #000;color: #fff;
}</style>

使用
页面初始化时输入框获取焦点,并平移键盘弹起的平移高度
初始化监听initKeyboardObserver

参考:
https://juejin.cn/post/7338335869709385780


http://www.ppmy.cn/ops/163390.html

相关文章

JavaWeb基础专项复习6(2)——AJAX补充

目录 1、load(url, [data], [callback]) 1.1 语法 1.2概述 1.3参数 url,[data,[callback]]String,Map/String,CallbackV1.0 1.4示例 HTML 代码: jQuery 代码: 2、get(url, [data], [callback], [type]) 2.1 语法 2.2 概述 2.3 参数 url,[data],[callback],[type]St…

【JavaScript—前端快速入门】JavaScript 综合案例 — 猜数字

JavaScript 综合案例—猜数字 预期效果 需求 完成基本的页面布局在文本框输入数字后&#xff0c;点击"猜"按钮&#xff0c;结果那一行会显示"猜大了"或者"猜小了"每猜一次&#xff0c;就会增加一次猜的次数猜到数字后&#xff0c;结果显示要猜的…

3d投影到2d python opencv

目录 cv2.projectPoints 投影 矩阵计算投影 cv2.projectPoints 投影 cv2.projectPoints() 是 OpenCV 中的一个函数&#xff0c;用于将三维空间中的点&#xff08;3D points&#xff09;投影到二维图像平面上。这在计算机视觉中经常用于相机标定、物体姿态估计、3D物体与2D图…

通俗易懂的分类算法之决策树详解

通俗易懂的分类算法之决策树详解 1. 什么是决策树&#xff1f; 决策树是一种像树一样的结构&#xff0c;用来帮助我们对数据进行分类或预测。它的每个节点代表一个问题或判断条件&#xff0c;每个分支代表一个可能的答案&#xff0c;最后的叶子节点就是最终的分类结果。 举个…

JAVA实战开源项目:安康旅游网站(Vue+SpringBoot) 附源码

本文项目编号 T 098 &#xff0c;文末自助获取源码 \color{red}{T098&#xff0c;文末自助获取源码} T098&#xff0c;文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…

Windows逆向工程入门之MASM字符处理机制

公开视频 -> 链接点击跳转公开课程博客首页 -> ​​​链接点击跳转博客主页 目录 一、MASM字符编码体系深度解析 1. 多层编码支持架构 编码转换关键技术&#xff1a; 2. 字符串存储优化策略 内存优化特征&#xff1a; 二、逆向工程中的字符串特征识别 1. 字符串解…

SOUI基于Zint生成EAN码

EAN码广泛应用与欧洲的零售业。包括EAN-2、EAN-5、EAN-8和EAN-12码。分别编码 2、5、7 或 12 位数字。此外&#xff0c;可以使用 字符将 EAN-2 和 EAN-5 附加符号添加到 EAN-8 和 EAN-13 符号中&#xff0c;就像 UPC 符号一样。 EAN-8校验码计算&#xff1a; 从左往右奇数位的…

计算机毕业设计SpringBoot+Vue.js社区智慧养老监护管理平台(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…