问题
iOS移动端呼起键盘时,会覆盖放在底部的按钮,如图所示。Android移动端则可以的跟随键盘一起呼起,不会被覆盖在底部。
键盘呼起后,按钮被遮挡。这当然不是我们期望的结果,接下来我们一起解决这个问题。
为什么?
ios移动端唤起软键盘时,页面的高度和视觉视口高度不一致,导致按钮被覆盖到底部。所以我们需要在视觉窗口高度变化时,手动设置页面高度。
如何设置视觉视口高度
官方为我们提供了Visual Viewport API ,它提供了当前页面的视觉视口接口,即 VisualViewport 。对于每个页面容器来说(如 iframe),都存在有一个独立的 window 对象。每个页面容器的 window 对象都有一个独立的 VisualViewport 属性。
你可以使用 Window.visualViewport 获得对应 window 的视觉视口 API。
当视觉视口被改变时,触发 resize 事件,因此通过使用 addEventListener() 或者将监听回调函数赋值给对应的 onresize 属性,添加事件监听。
iOS键盘呼起属于视觉窗口改变,因此可以使用下列代码(Vue3 composition api)获取视觉视口的高度所对应的 CSS 像素数。
// 获取视觉窗口的宽高
// 默认100%
export default function useVisualViewport () {
const rect = reactive({
height: '100%',
width: 0
})
if (!window.visualViewport) {
return rect
}
function resizeHandler () {
rect.height = window.visualViewport.height
rect.width = window.visualViewport.width
}
onBeforeMount(() => {
window.visualViewport.addEventListener('resize', resizeHandler)
})
onBeforeUnmount(() => {
window.visualViewport.removeEventListener('resize', resizeHandler)
})
return rect
}
然后设置到对应的dom即可达成我们的需求,如下图所示。
const boxStyle = computed(() => {
return {
height: rect.height + 'px'
}
})
兼容性
目前浏览器已基本支持 Visual Viewport API。 Safari 在 13.1 版中已经支持; 如果您对使用 API 感兴趣,请在仔细查阅浏览器支持表。
总结
按钮或者其他操作跟随键盘呼起还是很常见的需求,记录问题与大家分享。
Visual Viewport API 以及我之前写的两篇文章 Clipboard API:全新的异步复制、粘贴API 、CookieStore:操作cookie的原生API,都是新增的内容,浏览器功能越发强大,前端的道路任重而道远。
不仅仅是解决问题。多思考,是一件很有趣的事情。
如有表述不准确的地方,请大家指正。