主页 > 互联网  > 

IOS输入框聚焦会把内容区域顶起

IOS输入框聚焦会把内容区域顶起

前几天做了一个类似qq布局的h5的聊天界面,输入框固定在最底下。初始情况会有默认的两条聊天记录,但是当点击底部的输入框时,输入框聚焦,弹起键盘,然后整个界面就被顶上去了,然后那两条默认的聊天记录也被顶上去了,导致整个页面没内容了。

这张图片是初始页面 这张图片是点击输入框之后的样子,发现初始两条聊天内容被顶上去了

这里给出一个demo(如果样式有问题,请将浏览器的模拟器调到iphone 6/7/8)

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no,viewport-fit=cover" /> <title>Document</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } html, body { width: 100%; height: 100%; overflow: hidden; background-color: pink; } p { padding-bottom: 1.875rem; } .left { text-align: left; } .right { text-align: right; color: blue; } .chatContainer { height: 100%; padding-bottom: 30px; overflow: auto; } .inputBox { display: flex; position: fixed; bottom: 0; left: 0; right: 0; height: 30px; z-index: 999; } input { flex: 1; margin-right: .5rem; } button { width: 6.25rem; height: 100%; } </style> </head> <body> <div class="chatContainer"> <div class="flag"></div> <div class="chat"> <p class="left">你好,我是XXX,一个机器人</p> <p class="left">请问您需要问什么</p> </div> </div> <div class="inputBox"> <input type="text" /> <button>发送</button> </div> <script> let oBtn = document.querySelector('button') let oChatContainer = document.querySelector('.chatContainer') let oChat = document.querySelector('.chat') let oInput = document.querySelector('input') oBtn.onmousedown = (e) => { e.preventDefault() let inputValue = oInput.value if (!inputValue) return let oDiv1 = document.createElement('p') let oDiv2 = document.createElement('p') oDiv1.className = 'right' oDiv1.innerText = inputValue oDiv2.className = 'left' oDiv2.innerText = '感谢您的回复!' oChat.appendChild(oDiv1) oChat.appendChild(oDiv2) let timer = setTimeout(() => { clearTimeout(timer) oDiv2.scrollIntoView({ behavior: "smooth", }) }, 100) oInput.value = '' } </script> </body> </html>

感觉这个好像并没有什么问题,安卓可以正常的显示,交互。但是IOS就是不行,并且我还设置了

.inputBox { position: fixed; bottom: 0; z-index: 999; }

让我百思不得其解,,最后发现这是IOS手机的通病,没办法,只能进行hack了。

我的最终解决思路是,既然聚焦会定顶起内容区域,那么顶起来多少,我就用空白的元素占位多少高度,这样内容就显示出来了。当手指在屏幕滑动时,再把占位块高度变为0。如果内容区域足够高了,那么就不需要占位了,因为这个时候肯定有内容区域的元素露出来了。

最终的js代码如下

insetPlaceholder(oChatContainer, oInput) function insetPlaceholder(containerEl, inputEl) { /** * 只有苹果手机会导致输入框聚焦顶底整个内容区域, * 所有这个函数只对IOS系统进行兼容处理 */ let isIos = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); if (!isIos) return /** * 这里这个是一个死的元素结构 * 类似这样 * <div class="container"> <div class="flag"></div> <div class="content"></div> </div> * container是整体,flag是占位元素,根据情况切换高度 * content是实际的内容区域 */ let oFlag = containerEl.children[0] let oContent = containerEl.children[1] let firstFocusFlagElHeight = undefined // 能够显示出内容的最小高度 let showInfoMinHeight = undefined const onInputFocus = () => { /** * 记录第一次聚焦的时候,container这个大盒子究竟被顶起来多少,把这个值记录为flag的高度 * * 如果oContent的高度大于700了,那就说明内容足够多了,不需要占位元素顶了 */ if (firstFocusFlagElHeight === undefined || (oContent.offsetHeight < showInfoMinHeight)) { let timer = setTimeout(() => { clearTimeout(timer) if (firstFocusFlagElHeight === undefined) { firstFocusFlagElHeight = Math.abs(oFlag.getBoundingClientRect().top) showInfoMinHeight = firstFocusFlagElHeight + oContent.offsetHeight } oFlag.style.height = firstFocusFlagElHeight + 'px' }, 3e2) } } oInput.addEventListener('focus', onInputFocus) /** * 监听这个事件主要是为了隐藏那个占位元素 * 防止用户滑动界面把占位元素露出来 * 并且很奇怪,如果不这样做,输入框会滚动!并且我已经设置了固定定位! */ const onContainerElTouchstart = () => { oFlag.style.height = 0 oInput.blur() } containerEl.addEventListener('touchstart', onContainerElTouchstart) }

或者如果你的初始内容足够多,那你也不需要考虑这个问题

这里需要注意的是insetPlaceholder方法传入第一个参数是需要一个特定的html结构的,需要这样的结构

<div class="container"> <div class="flag"></div> <div class="content"></div> </div>

还有两个注意点这里说一下

oDiv2.scrollIntoView({ behavior: "smooth", })

这段代码用setTimout包裹了,不然动画无法执行(IOS不支持这个方法,只有安卓可以)

这里按钮的点击是监听的mousedown事件,并不是click,主要是为了阻止按钮点击触发输入框的失焦,会导致键盘收起,影响用户体验。
标签:

IOS输入框聚焦会把内容区域顶起由讯客互联互联网栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“IOS输入框聚焦会把内容区域顶起