小程序自定义导航栏

1,663 阅读3分钟

最近在微信小程序项目中有webview嵌入活动页的需求,发现微信小程序没法配置导航栏,只能使用自定义组件模拟实现导航栏,所以打算自己写一个。

配置自定义导航

首先贴上官方文档

developers.weixin.qq.com/miniprogram…

{
  "component": true,
  "usingComponents": {
    "navbar": "/components/navbar/navbar"
  }
}

页面配置navigationStyle设置为custom的时候可以使用此组件替代原生导航栏,设置后效果

设置完之后内容就是以最顶部为起点

接下来使用自定义组件navbar来实现顶部样式与返回首页胶囊

自定义组件

首先分析下导航栏布局:

  • 顶部状态栏
  • 主要内容区
    • 胶囊
    • title

布局分析完之后,接下来就是代码实现

wxml

<!-- index.wxml -->
<navbar header="{{header}}"></navbar>
<view class="intro">项目内容</view>

<!-- navbar -->
<view style="height:{{statusHeight+navHeight}}px"></view>
<view class='topbar' style="background:{{header.headerbg}}">
  <view class='status' style="height:{{statusHeight}}px"></view>
  <view class='navbar' style="height:{{navHeight}}px">
      <view class='navbar_home' style="background:{{header.capsulebg}};border:{{header.capsuleborder}}">
        <text class="iconfont iconback" wx:if="{{header.backCapsule}}" bindtap='backClick'></text>
        <text class="iconfont iconhome" wx:if="{{header.homeCapsule}}" bindtap='homeClick'></text>
      </view>
      <view class='navbar_title' style="height:{{navHeight}}px">
        <view style="color:{{header.fontColor}};font-size:{{header.fontSize}}">{{header.title}}</view>
      </view>
  </view>
</view>

topbar为最外层view,提供动态配置背景颜色

status为最上面的状态栏,不同机型高度不确定,所以这一块高度也是动态的

navbar为整个自定义区域,不同机型也是高度不确定,所以也是使用变量

navbar下面的 navbar_home 展示自定义胶囊;也需要提供背景颜色可定制,胶囊提供两个按钮,一个返回按钮一个主页,图标使用的是iconfont

navbar_title用于展示标题,这里垂直居中展示就行,提供配置颜色与大小

整个导航需要一直固定在最上面,所以使用fixed定位,最上层div用来占位

wxss

.topbar {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 9999;
}
.status {
  width: 100%;
}
.navbar {
  width: 100%;
  display: flex;
  justify-content: flex-start;
  align-items: center;
  text-align: center;
  position: relative;
}

.navbar_home {
  position: absolute;
  left: 32rpx;
  display: flex;
  justify-content: flex-start;
  align-items: center;
  border-radius: 33rpx;
  border: 1px solid rgba(0, 0, 0, 0.1);
  background: rgba(0,0,0,0.2);
  box-sizing: border-box;
  padding: 10rpx 0;
}

.navbar_home .iconfont {
  padding: 0 20rpx;
}

.navbar_home .iconfont:nth-child(2) {
  border-left: 1px solid #333;
  opacity: 0.7;
}

.navbar_title {
  position: absolute;
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: -1;
}
.navbar_title view {
  width: 40%;
  word-break: break-all;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 38rpx;
}

js

逻辑处理:主要是高度计算,与两个按钮的点击事件

高度计算:

通过小程序提供api wx.getSystemInfo来动态获取高度与机型

statusBarHeight 状态栏的高度,单位px

通过res.system来判断ios还是andriod,如果是ios 导航栏为44px,andriod为48px

胶囊事件:

点击主页按钮则直接使用wx.switchTab回到主页

点击返回事件先通过getCurrentPages判断调用栈,如果为空直接回到首页

Component({
  properties: {
    header: {
      type: Object,
      value: {
        homeCapsule: true, // 是否展示首页
        backCapsule: true, // 是否展示返回
        headerbg: "#fff", // 背景颜色
        title: "", // 标题
        fontColor: "#000", // 字体颜色
        fontSize: '16', // 标题字体大小
        capsulebg: 'rgba(0,0,0,0.2)', // 胶囊样式
        capsuleborder: '1px solid rgba(0, 0, 0, 0.1)',
        capsulesep: '1px solid rgba(255,255,255,0.2)'
      }
    }
  },

  options: {
    styleIsolation: 'apply-shared',
  },

  methods: {
    backClick() {
      if (getCurrentPages().length == 1) {
        this.homeClick()
      } else {
        wx.navigateBack({
          delta: 1
        })
      }
    },
    homeClick() {
      wx.switchTab({
        url: '/pages/homepage/homepage',
      })
    }
  },
  attached() {
    var self = this;
    wx.getSystemInfo({
      success(res) {
        var isIos = res.system.indexOf('iOS') > -1;
        self.setData({
          statusHeight: res.statusBarHeight,
          navHeight: isIos ? 44 : 48
        })
      }
    })
  }
})

完成后效果图

因为navbar组件是通用组件,在app.json配置,最后提供完整的代码片段

自定义小程序导航

总结

  • 使用"navigationStyle": "custom"配置项使导航可配置
  • 使用自组件在动态配置所需要的功能与样式
  • 通过wx.getSystemInfo API来解决兼容问题