前提
在开发小程序的过程中,会经常使用到input
组件,其聚焦的时候,会在必要时自动上移整个页面以便弹起的键盘不回遮住input
组件
但是当页面应用自定义导航时,聚焦时会把自定义导航也上移,而这就不符合我们的预期,我们希望的是导航栏始终固定在顶部,下面的内容上移即可!参见该帖子
为了解决这个问题,我们只好自己来处理页面上移的事情了!
准备工作
首先我们需要先关闭掉输入框自动上移页面的功能
<input type="text" adjust-position="{{false}}" />
接下来我们就要自己处理页面上移的工作了
为了让除了导航栏的区域整体上移, 我们需要先可以定义一个值(top)来表示上移距离
// index.js
Page({
data: {
top: 0
}
})
其次 需要固定好页面的结构, 如下: 我们要做的便是只上移.cointainer
这个组件, 故使用top: -{{top}}px
来表示内容上移
// index.wxml
<mp-navigation-bar background="#d8d8d8" title="导航栏标题"></mp-navigation-bar>
<view class="container" style="position: relative; top: -{{top}}px">
内容区域
</view>
计算上移距离
我们先思考什么情况下, 页面需要上移?
显然是input
距离底部的距离小于弹出的键盘高度的时候需要上移, 而上移的距离便是距离底部的距离与键盘高度的差
那么只需要知道这两个值便可实现该功能了.
键盘高度
翻阅input的文档, 我们发现监听bindfocus
或者bindkeyboardheightchange
事件都可以获取到键盘的高度
// index.wxml
# index.wxml
<input id="input1" type="text" adjust-position="{{false}}" bindfocus="onHandleFocus" bindblur="onBlur" />
// index.js
onHandleFocus (e) {
console.log('focus', e)
const keyboradHeight = e.detail.height
}
距离底部的距离
首先我们需要货值输入框的位置, 这里可以使用SelectorQuery
来获取输入框的位置
# index.js
onHandleFocus (e) {
console.log('focus', e)
const keyboradHeight = e.detail.height
const id = e.currentTarget.id
this.createSelectorQuery()
.select(`#${id}`)
.boundingClientRect(rect => {
console.log('==> rect', rect)
}).exec()
}
获取到的rect对象同DOM的getBoundingClientRect
, 然后我们再观察这张图片:
显然要计算输入框距离底部的距离只需用显示高度减去bottom即可
页面的显示高度可以用如下方法获得
const { windowHeight } = wx.getSystemInfoSync()
最后我们上诉思路整理成对应代码
# index.js
onHandleFocus (e) {
console.log('focus', e)
const keyboradHeight = e.detail.height
const id = e.currentTarget.id
this.createSelectorQuery()
.select(`#${id}`)
.boundingClientRect(rect => {
console.log('==> rect', rect)
const { windowHeight } = wx.getSystemInfoSync()
const bottom = windowHeight - rect.bottom
if (bottom > keyboradHeight) {
// 距离足够, 不需要上移
return
}
this.setData({
top: keyboradHeight - bottom
})
}).exec()
}
完整代码见该代码片段
尾声
该方法虽然能够解决标题所述的问题,当也存有其他问题:
- 页面结构必须固定结构(分为标题-内容两大块)
- 所有的
input
都必须加上id
,否则createSelectorQuery
选择器没法找到对应的input
,且必须监听focus
和blur
方法。 - 最外层的内容
view
的top
样式被占用
PS: 计算上移距离的这部分代码可以写成一个behavior
方便其他页面直接引入