Visual Viewport API 提供了当前页面的视觉视口接口,即 VisualViewport 。对于每个页面容器来说(如 iframe),都存在有一个独立的 window 对象。每个页面容器的 window 对象都有一个独立的 VisualViewport 属性。
你可以使用 Window.visualViewport 获得对应 window 的视觉视口 API。
可以间接获取iOS端键盘的高度,解决一些键盘弹出造成的布局问题(iOS13支持)。
实际问题
h5页面布局中,顶部为‘注意事项’,底部固定为输入框。在iOS设备预览时,当键盘弹起的时候,看不到顶部的注意事项。
直观来说,问题导致的原因是键盘弹起的时候,iOS端的webview不会改变尺寸。因此导致顶部的注意事项被顶上去了。
解决方案:
方案1:
配合移动原生端处理(如果是自己的app),当键盘弹出或者收起的时候,调用原生端调整webview的高度。
swift
/// 键盘缩放的时候是需要调整大小
var resizeWindowOnKeyboardAppear = false {
didSet {
if resizeWindowOnKeyboardAppear == false {
webView.snp.remakeConstraints { [weak self] make in make.top.left.right.bottom.equalToSuperview()
}
}
}
}
@objc func keyboardWillShow(_ notification: Notification) {
// 获取键盘的高度:(notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height
if resizeWindowOnKeyboardAppear {
if let keyboardHeight = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height {
webView.snp.remakeConstraints { make in make.left.right.top.equalToSuperview()
make.bottom.equalToSuperview().offset(-keyboardHeight)
}
}
}
}
/// 键盘缩放的时候是需要调整大小
var resizeWindowOnKeyboardAppear = false {
didSet {
if resizeWindowOnKeyboardAppear == false {
webView.snp.remakeConstraints { [weak self] make in make.top.left.right.bottom.equalToSuperview()
}
}
}
}
@objc func keyboardWillShow(_ notification: Notification) {
// 获取键盘的高度:(notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height
if resizeWindowOnKeyboardAppear {
if let keyboardHeight = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height {
webView.snp.remakeConstraints { make in make.left.right.top.equalToSuperview()
make.bottom.equalToSuperview().offset(-keyboardHeight)
}
}
}
}
方案2: 使用 visualViewport
, 示例代码:
js
// 页面顶部增加一个元素,用于弹出键盘时,将注意事项撑下去
<div
id="con-container"
:style="{'height': keyboardHeightHandle.keyboardHeight + 'px'}"
>
</div>
// 页面加载完成时
this.keyboardHeightHandle.originHeight = window.visualViewport.height;
window.addEventListener('scroll', this.handleOnScroll);
window.visualViewport.addEventListener('resize', this.handleResizeEvent);
/* 弹出键盘时,防止用户滚动最外层看到空白*/
function handleOnScroll () {
if (this.keyboardHeightHandle.keyboardHeight > 0) {
this.$refs.inputRef.blur();
}
},
/* 处理键盘问题*/
function handleResizeEvent () {
const kbHeight = this.keyboardHeightHandle.originHeight - window.visualViewport.height;
// 可能存在用户拖拽固定,导致键盘不准,这里额外判断
if (kbHeight != 0 && kbHeight < this.keyboardHeightHandle.keyboardHeight) {
return;
}
if (kbHeight == 0) {
this.keyboardHeightHandle.keyboardHeight = kbHeight;
} else {
setTimeout(() => {
this.keyboardHeightHandle.keyboardHeight = kbHeight;
// 滚动到最底部
if (this.$refs.contentRef) {
this.$refs.contentRef.scrollTop =
this.$refs.contentRef.scrollHeight;
}
}, 200);
}
}
// 页面顶部增加一个元素,用于弹出键盘时,将注意事项撑下去
<div
id="con-container"
:style="{'height': keyboardHeightHandle.keyboardHeight + 'px'}"
>
</div>
// 页面加载完成时
this.keyboardHeightHandle.originHeight = window.visualViewport.height;
window.addEventListener('scroll', this.handleOnScroll);
window.visualViewport.addEventListener('resize', this.handleResizeEvent);
/* 弹出键盘时,防止用户滚动最外层看到空白*/
function handleOnScroll () {
if (this.keyboardHeightHandle.keyboardHeight > 0) {
this.$refs.inputRef.blur();
}
},
/* 处理键盘问题*/
function handleResizeEvent () {
const kbHeight = this.keyboardHeightHandle.originHeight - window.visualViewport.height;
// 可能存在用户拖拽固定,导致键盘不准,这里额外判断
if (kbHeight != 0 && kbHeight < this.keyboardHeightHandle.keyboardHeight) {
return;
}
if (kbHeight == 0) {
this.keyboardHeightHandle.keyboardHeight = kbHeight;
} else {
setTimeout(() => {
this.keyboardHeightHandle.keyboardHeight = kbHeight;
// 滚动到最底部
if (this.$refs.contentRef) {
this.$refs.contentRef.scrollTop =
this.$refs.contentRef.scrollHeight;
}
}, 200);
}
}
其他参考示例: css - How to make fixed-content go above iOS keyboard? - Stack Overflow