移动端软键盘踩坑指南

本文为在工作中遇到的有关移动端软键盘的问题总结,可能随着移动端系统更新有所变化,请结合实际情况食用本文。

每部分内容配有演示 demo,可通过浏览器 devTool 查看源代码。

前端开发的一大痛苦源泉是需要适配不同的设备。好比在写 css 的时候,在深呼吸写下第一行样式代码的时候,你需要先从别的什么地方拷贝下来一下叫 reset.css 或者 normalize.css 来抹平一些差异。

不幸的是,不是所有的问题都能像 css 这样方便的抹平,像键盘输入这种常见的需求,也可能一不留神掉进坑里 🤯。

希望你在掉进坑里时,无奈地在互联网上搜索"如何解决移动端键盘输入XXX问题时"找到本文,能对你有所帮助,我们开始吧!

软键盘弹起后怎么内容区域变了?

iOS 和 android 的软键盘弹起表现是有差异的!

iOS:

android:

很多文章解释过这个问题,这里总结如下:

  • iOS:软件盘弹起后页面高度不变 。页面向上滚动,滚动高度为软键盘高度;
  • android:页面高度减小,减小高度为软键盘高度。

👉 戳我查看 demo 使用手机浏览器食用更佳🍬

有没有办法抹平这个问题呢?

我们在工作中选用的方式是将 android 设备同 iOS 一样保持高度不变,可以在页面初始化时设置 viewport 实现,代码如下:

js 复制代码
if (/Android/.test(navigator.userAgent)) {
  const viewportMeta = document.querySelector('meta[name=viewport]')
  const resetViewportHeight = () => {
    let content = (viewportMeta.getAttribute('content') ?? '')
      .split(',')
      .map((str) => str.trim())
      .filter((str) => str.length)
      .map((str) => str.split('=').map((str) => str.trim()))
      .filter(([name]) => name !== 'height')
      .map((pair) => pair.join('='))
      .join(',')

    content += `,height=${window.innerHeight}px`
    viewportMeta.setAttribute('content', content)
  }

  resetViewportHeight()

如何获取软件盘高度?

window.visualViewport.height 可以拿到拿到可视区域大小,比如在 iphone 14 plus 手机上,未触发键盘时 window.visualViewport.height 是746,触发了软键盘时是466。

但是在 iOS 手机上有个坑,在触发软键盘的瞬间获取的 window.visualViewport.height 是不确定的,可能是 746 也可能是 466,解决办法是通过 resize 事件来监听变化:

javascript 复制代码
window.visualViewport.addEventListener("resize", resizeHandler)

获取到软件盘高度可以实现如下图这种输入效果:

👉 戳我查看 demo 使用手机浏览器食用更佳🍬

回车键的文字可以修改吗?

enterkeyhint 属性可以定义虚拟键盘上的回车键文案,用手机测试了一番,测试如下:

input(iOS) textarea(iOS) input(Android) textarea(Android)
-- 换行(return) 换行(return) Go 回车符号
enter 换行(return) 换行(return) 回车符号 回车符号
done 完成(done) 完成(done) Done Done
search 搜索(search) 搜索(search) 搜索符号 搜索符号

括号内是英文系统下的文案

测试发现 iOS 和安卓表现并不一致,input 和 textarea 也不一致。更奇怪的是,iOS 中文输入法中,input 默认当回车键文字是换行,但是 input 其实并不能换行。

结论:目前并无可靠的办法修改回车键文案。

如何让内容撑开 textarea?

用到多行文本时,需要使用 textarea。

textarea 存在一个问题是:textarea 高度无法由内容撑开,一旦内容超过 textarea 高度,会变成内部滚动。如果需要由内容撑开 textarea 高度。可以通过添加一个隐藏的 div 节点,由节点高度撑开。具体实现看demo:

👉 戳我查看 demo 使用手机浏览器食用更佳🍬

中文输入法计算长度有个坑

当需要限制文字长度时,中文输入可能会存在一个问题:

如图所示,在打字过程中,input.value.length 会记录当前拼音和空格的总长度,如果 input 框限制输入 4 个字的场景下,用 input.value.length 来判断长度就会出现字打到一半就不能再输入的问题。

可以通过 composition 事件判断是否处于输入法中。效果如下:

👉 戳我查看 demo 使用手机浏览器食用更佳🍬

长按事件表现不一致

记录一个 iOS 和 Android 长按输入框的差异:

  • iOS 长按后不会触发 focus 事件;
  • Android 长按后不会触发 focus 事件。
相关推荐
像风一样自由202034 分钟前
HTML与JavaScript:构建动态交互式Web页面的基石
前端·javascript·html
aiprtem1 小时前
基于Flutter的web登录设计
前端·flutter
浪裡遊1 小时前
React Hooks全面解析:从基础到高级的实用指南
开发语言·前端·javascript·react.js·node.js·ecmascript·php
why技术1 小时前
Stack Overflow,轰然倒下!
前端·人工智能·后端
GISer_Jing2 小时前
0704-0706上海,又聚上了
前端·新浪微博
止观止2 小时前
深入探索 pnpm:高效磁盘利用与灵活的包管理解决方案
前端·pnpm·前端工程化·包管理器
whale fall2 小时前
npm install安装的node_modules是什么
前端·npm·node.js
烛阴2 小时前
简单入门Python装饰器
前端·python
袁煦丞3 小时前
数据库设计神器DrawDB:cpolar内网穿透实验室第595个成功挑战
前端·程序员·远程工作
天天扭码3 小时前
从图片到语音:我是如何用两大模型API打造沉浸式英语学习工具的
前端·人工智能·github