-
在微信小程序社区看到有遇到同类情况的问题: developers.weixin.qq.com/community/d… developers.weixin.qq.com/community/d…
-
问题:小程序中在有底部tabbar时,无法直接获取底部tabbar高度,导致可滚动区域的高度值计算不准确,在scrollview上下滚动时,容易触发外层page滚动条显示,出现双滚动条。尤其当scrollview滚动至底部时不能完全展示完整内容,需再次将外层page滚动条滑动至底部才能看到完整内容,即tabbar遮挡底部内容。影响功能、用户体验不好、也不美观。
-
问题预览:
-
方案:
在页面底部增加view#bottomWatch,设置绝对定位,作为可滚动区域底部边界。(也可通过它和屏幕高度计算获取到实际底部tabbar高度)
蓝块:#bottomWatch滚动区下边界距离顶部距离,即不含底部tabbar的屏幕高度
红块:滚动区上边界距离顶部距离
黄块:在顶部导航吸顶后需隐藏的动态内容区域高度(如不需要,可忽略)
预览:
完整代码:
页面中使用方式: 1.index.wxml:
<view id="bottomWatch" class="bottom-watch">
</view>
index.wxss:
.bottom-watch {
position: absolute;
bottom: 0;
width: 100%;
height: 1px;
background: transparent;
visibility: hidden;
}
index.js:
import setRealHeight from "../../api/setRealHeight"
Page({
onload() {
setRealHeight.bind(this, {
topBoundaryClass: ".tab-bar",//顶部分类导航选择器
dynamicHeightClass: ".adCard",//顶导上的其他动态隐藏和显示内容区选择器
})()
//或者
setRealHeight.bind(this, {
topBoundaryClass: ".tab-bar",//顶部分类导航选择器
})()
}
})
setRealHeight.js:
/**
*
* @method handleSelectorQuery 内部使用
* @params {
* className: "", 监听的元素选择器
* rectElement: "", 所需rect中的具体元素,rect值参考:https://developers.weixin.qq.com/miniprogram/dev/api/wxml/NodesRef.boundingClientRect.html
* heightObjElement: "", 作为接收结果属性
* heightObj: {}, 接收结果,用于setdata前的结果计算
* }
*
* @method setRealHeight 对外接口
* @params {
* topBoundaryClass: "", 所需结果高度的上边界的选择器名,用于计算距离元素#bottomWatch之间的高度
* dynamicHeightClass: "", 高度动态变化元素的选择器名,如吸顶效果中发生变化的元素
* }
*/
function handleSelectorQuery(params = {
className: "",
rectElement: "",
heightObjElement: "",
heightObj: {},
}) {
const {
className, rectElement, heightObjElement, heightObj,
} = { ...params }
return new Promise((resolve, reject) => {
wx.createSelectorQuery().select(`${className}`).boundingClientRect((rect) => {
if (rect && rect[`${rectElement}`]) {
heightObj[`${heightObjElement}`] = rect[`${rectElement}`]
resolve()
} else {
reject()
}
}).exec()
})
}
export default function setRealHeight(params = {
topBoundaryClass: "",
dynamicHeightClass: "",
}) {
const heightObj = {}
const topBoundaryHeightPromise = params.topBoundaryClass && handleSelectorQuery({
className: params.topBoundaryClass,
rectElement: "bottom",
heightObjElement: "topBoundaryHeight",
heightObj,
})
const dynamicHeightPromise = params.dynamicHeightClass && handleSelectorQuery({
className: params.dynamicHeightClass,
rectElement: "height",
heightObjElement: "dynamicHeight",
heightObj,
})
Promise.all([topBoundaryHeightPromise, dynamicHeightPromise]).then(() => {
const query = wx.createSelectorQuery()
query.select("#bottomWatch").boundingClientRect()
query.selectViewport().scrollOffset()
query.exec((res) => {
if (res && res[0]) {
const tempData = res[0].bottom - heightObj.topBoundaryHeight
const resultData = {
realWinHeight: tempData,
}
if (params.dynamicHeightClass) {
resultData.realWinHeightOfFixTab = tempData + heightObj.dynamicHeight
}
this.setData(resultData)
}
})
})
}