返回

解决iOS Safari虚拟键盘延迟:布局优化技巧

javascript

iOS Safari 虚拟键盘调整延迟问题

移动设备上,网页应用常常需要响应虚拟键盘的弹出和隐藏。iOS Safari浏览器中,当用户点击输入框唤起虚拟键盘时,页面resize事件触发可能存在延迟。这可能导致页面内容调整的滞后,影响用户体验。

问题分析

一般情况下,浏览器在窗口大小发生变化时会触发resize事件。在iOS Safari中,当虚拟键盘弹出时,页面高度减少,理应立即触发resize事件。不过,实际观察发现,该事件的触发往往是在键盘动画完成之后。也就是说,resize事件的响应要滞后于虚拟键盘的显示动画。 这可能源于Safari内部的事件处理机制,也可能是某些性能优化策略的结果。这样的延迟对一些需要即时调整页面布局的应用,比如聊天窗口、表单等,会带来不良体验。

解决方案

解决延迟问题的核心在于如何在虚拟键盘出现的第一时间得到通知,而不是等待resize事件。以下提供一些方法。

1. 借助 visualViewport API

visualViewport API提供了关于可视化视口的信息,可以更细粒度地控制页面的布局。与窗口的 window.innerHeight 不同, visualViewport.height 代表当前实际的可视区域高度,它会在键盘出现时立即变化。我们可以利用visualviewportresize事件,以获取更为及时的布局更新。

代码示例:

const visualViewportResize = () => {
    const visibleHeight = visualViewport.height;
  	// 可在此处处理页面高度变化
    console.log(`Viewport height changed to: ${visibleHeight}`);
};


if (window.visualViewport) {
  window.visualViewport.addEventListener('resize', visualViewportResize);
}

操作步骤:

  1. 将代码添加到页面的 JavaScript 中。
  2. visualViewportResize 函数内编写处理高度变化的逻辑。
  3. 当键盘弹出或者隐藏时,visualViewportresize 事件会被触发。

这种方法的优势在于,它可以立即反映出可见区域的变更。请注意,部分浏览器可能不支持visualViewport。为了兼容不支持此API的浏览器,你可以同时监听 window.resize事件做为兜底方案。

2. 利用 focusblur 事件配合 requestAnimationFrame

另一种思路是使用输入框的focusblur事件。在输入框获得焦点时,可以利用 requestAnimationFrame 推迟执行代码,该API会在下一次浏览器重绘前执行。这样可以获得更好的性能,减少延迟感。

const inputField = document.querySelector('input, textarea');
const focusHandler = () => {
    requestAnimationFrame(() => {
        // 在此调整布局
        console.log('Input has been focused.');
     });
}
const blurHandler = () =>{
    requestAnimationFrame(()=>{
        //  在此处调整布局
        console.log("Input has been blurred")
    })
}
inputField.addEventListener('focus', focusHandler);
inputField.addEventListener('blur',blurHandler)

操作步骤:

  1. 将上述代码放入JavaScript代码中
  2. 修改对应的 focusHandlerblurHandler 内容,放入需要的布局调整逻辑。
  3. 该方法适用于所有输入框元素(如 <input>, <textarea> 等)。
  4. 该方法会在输入框获得/失去焦点时进行对应的调整操作,但是并非所有虚拟键盘事件都能直接反映到input上。请结合visualViewport使用。

该方法相比于直接使用window.resize, focus/blur事件更可靠。requestAnimationFrame也保证了在浏览器的下次绘制时才执行布局变化。

其他建议

  • 避免过度依赖 window.innerHeight: window.innerHeight可能会因为虚拟键盘,或者浏览器工具栏发生变化,需要注意。使用visualViewport可以提供更精准的高度数据。
  • 性能优化: 在布局调整逻辑中,请注意代码性能,尽量减少复杂计算,避免引发卡顿。
  • 多端测试: 在不同设备和操作系统版本中测试页面,以保证良好的用户体验。
  • 回退策略: 针对不支持 visualViewport API的环境,采用传统的 window.resize 事件作为后备方案, 增加页面兼容性。
  • 适当的节流或防抖: 考虑到浏览器事件可能频繁触发,在 resize 或者焦点事件中适当地添加节流或防抖逻辑可以减少布局调整次数。

通过这些技术手段,开发者能够更好地应对iOS Safari中虚拟键盘带来的布局调整延迟问题,实现更为流畅和响应迅速的网页体验。