如何在uni-app中计算出微信小程序导航栏的高度

6,892 阅读4分钟

为什么要拿到导航栏的高度

拿到导航栏的高度当然是为了自定义导航栏uniapp默认为我们提供了一个导航栏,也就是每个页面上面的标题,但如果对这个默认的导航栏不满意,我们就可以选择自定义导航栏,比如我在下面,为了满足业务需求,放了一个搜索框,取代了原先的标题栏。

image-20220319133342326

不仅仅是在导航栏放放东西,如果你要导航栏自定义大背景,也需要自定义导航栏,如下(图片来源网络):

image-20220319133244566

小程序头部的几个参数

如果我们要开启页面自义定导航栏,以首页index为例,我们要在pages.json中加入以下代码,它默认是default

image-20220319134134085

我们再来看看几个参数

  • 头部高度
  • 状态栏高度
  • 导航栏高度(标题栏高度)
  • 微信小程序小胶囊的位置信息

头部高度

我们可以把小程序页面分为三块,一个是页面的头部,就是图片所示的部分,还有就是页面的主体,平时我们写代码那块,最后就是尾部tabbar那块。

image-20220319131537760

状态栏高度

状态栏就是我们手机显示电量,wifi的那部分,也算是头部的组成之一。这个状态栏高度我们可以很轻易地就能拿到,也就是调用uni.getSystemInfoSync().statusBarHeight

image-20220319185737373

导航栏高度(标题栏)

导航栏就是默认的标题栏,微信小程序的小胶囊是在导航栏垂直居中的,我们要说的就是算导航栏的高度。

image-20220319135352677

这个我们在不能在uniapp中直接拿到,可以看看官方的文档,我们要拿的就是微信小程序的导航栏高度。

image-20220319135809448

微信小程序小胶囊的位置信息

其实我们调用原生微信小程序api也不能直接拿到导航栏高度......,但我们可以拿到微信小程序右上角小胶囊的宽高定位信息,我们可以调用原生微信小程序api拿到,这些信息我们后面算导航栏高度的时候要用到。

image-20220319140141386

image-20220319140321949

这个小胶囊的定位信息是相对于小程序头部来看的

// #ifdef MP-WEIXIN
// 获取微信胶囊的位置信息 width,height,top,right,left,bottom
const custom = wx.getMenuButtonBoundingClientRect()
// console.log(custom)
// #endif

计算微信小程序的导航栏高度

因为每一个部手机的导航栏高度是不一样的,我们应该动态的去获取导航栏的高度,像上面的搜索框,我们要怎么让搜索框和微信小胶囊垂直居中呢,因为小胶囊是在导航栏中垂直居中,所以我们也要让搜索框在导航栏中垂直居中,那么我们就要拿导航栏的高度,然后就可以轻松的通过flex布局实现垂直居中了。

计算公式

先看一下图吧

image-20220319141800793

因为小胶囊在导航栏中是垂直居中的,所以说,小胶囊距离导航栏顶部的距离和距离底部的距离是一样的,由此我们可以推算出计算公式:

  • 导航栏的高度 = 胶囊高度 + (顶部距离 - 状态栏高度) * 2
  • 头部高度 = 导航栏高度 + 状态栏高度

然后我的建议是可以把这写参数封装在uniapp的全局的变量globalData中,哪个页面要用就可以直接拿,而且拿起来也非常方便。

我们不需要用vuex去管理,因为这个一开始就确立的,后面不用改,并不涉及状态管理

代码实现

最后,再来看看我写的代码吧。

App.vue

<script>
export default {
  globalData: {
    statusBarHeight: 0, // 状态导航栏高度
    navHeight: 0, // 总体高度
    navigationBarHeight: 0, // 导航栏高度(标题栏高度)
  },
  onLaunch: function () {
    console.log("App Launch")

    // 状态栏高度
    this.globalData.statusBarHeight = uni.getSystemInfoSync().statusBarHeight

    // #ifdef MP-WEIXIN
    // 获取微信胶囊的位置信息 width,height,top,right,left,bottom
    const custom = wx.getMenuButtonBoundingClientRect()
    // console.log(custom)

    // 导航栏高度(标题栏高度) = 胶囊高度 + (顶部距离 - 状态栏高度) * 2
    this.globalData.navigationBarHeight = custom.height + (custom.top - this.globalData.statusBarHeight) * 2
    // console.log("导航栏高度:"+this.globalData.navigationBarHeight)

    // 总体高度 = 状态栏高度 + 导航栏高度
    this.globalData.navHeight = this.globalData.navigationBarHeight + this.globalData.statusBarHeight

    // #endif

    console.log(this.globalData)
  },
  onShow: function () {
    console.log("App Show")
  },
  onHide: function () {
    console.log("App Hide")
  },
}
</script>

我们可以做的更好些,把这个封装到mixin.js,我们哪个页面要用这些参数,就直接导入混入,然后在生命周期onLoad中调用下就好了。

mixin.js

export const systemInfo = {
  data: () => ({
    statusBarHeight: 0,
    navigationBarHeight: 0,
    navHeight: 0,
    windowHeight: 0, // 可使用窗口高度
  }),

  methods: {
    // 获取设备信息
    getSystemInfo() {
      this.statusBarHeight = getApp().globalData.statusBarHeight
      this.navigationBarHeight = getApp().globalData.navigationBarHeight
      this.windowHeight = uni.getSystemInfoSync().windowHeight
      this.navHeight = getApp().globalData.navHeight
    },
  },
}

image-20220319150304609

补充

还有一个点要说的是:我为什么不在globalData中直接去拿可使用窗口高度windowHeight呢?

这也是我踩的一个坑,我们讲讲可使用窗口高度,我们不定义导航栏,那么

  • windowHeight = 屏幕高度 - tabbar高度 - 头部高度

如果我们自定义了导航栏,则

  • windowHeight = 屏幕高度 - tabbar高度

我们并不是每个页面的都要自定义导航栏,那么,每个页面的windowHeight是有所不同的,所以说,我们不能在小程序加载后,就定死windowHeight,我们应该根据每个页面去拿windowHeight

结语

感谢读完本篇文章,希望对你能有所帮助,如有问题欢迎各位在评论区指正。

创作不易,希望可以点个赞支持一下❤️❤️。