微信小程序自定义导航栏组件
场景:在小程序项目开发过程中,遇到一个需求是导航栏及下面一块地方需要放一张背景图(整体),由于导航栏不支持配置图片,查阅相关资料,最终解决方案如下
1、在微信项目的app.json中配置windpw对象的navigationStyle属性为custom,此时所有页面导航都是自定义,仅保留右边胶囊
2、自定义导航组件,该组件需要适配各种机型及自定义返回按钮事件等
遇到的问题:
1、各种机型上如何让自定义的title上下居中,与胶囊在同一水平线上
2、组件公用返回事件如何定义
分析
上图是两个不同机型顶部导航栏效果图,要实现title栏上下居中,我们必须知道状态栏高度(刘海区域),及底部胶囊容器的高度(红色框)
通过微信官方接口可以获取到胶囊按钮高度A,胶囊上边缘到顶部的距离B以及状态栏高度C
胶囊容器的高度 = A+(B-C)*2
官方接口
wx.getSystemInfo:该接口的返回参数包含C(statusBarHeight) 戳>>.
wx.getMenuButtonBoundingClientRect()该接口返回的参数包含A(height),B(top) 戳>>.
代码:
wx.getSystemInfo({
success: e => {
let StatusBar = e.statusBarHeight;
let rect = wx.getMenuButtonBoundingClientRect();
let HeaderBar = rect.height + (rect.top - e.statusBarHeight) * 2; //胶囊容器高度
let CustomBar = HeaderBar + e.statusBarHeight; //胶囊容器高度加状态栏高度
this.globalData.headerBarHeight = HeaderBar
this.globalData.customBarHeight = CustomBar
}
})
此段代码可以放到全局的app.js中,后续直接获取对应值使用
注:由于胶囊按钮是原生组件,为表现一致,其单位在各种手机中都为px,所以我们自定义导航栏的单位都必需是px(切记不能用rpx),才能完美适配。
整个导航组件代码:
wxml
<!--pages/components/navBar/navBar.wxml-->
<view class="nav-bar-box">
<view class="login-com" wx:if="{{bgFlag}}">
<view class="title" style="padding-top:{{statusBarHeight}}px;hieght:{{headerBarHeight}}px;line-height:{{headerBarHeight}}px">
<text>登录</text>
</view>
<image src="{{imageHost + 'login-background.png'}}"></image>
</view>
<view class="other-com" wx:else>
<view class="title" style="padding-top:{{statusBarHeight}}px;hieght:{{headerBarHeight}}px;line-height:{{headerBarHeight}}px;padding-right:{{back? '44': ''}}px">
<view class="icon-wrap" wx:if="{{back}}" bindtap="onBack">
<text class="icon iconfont iconfanhui"></text>
</view>
<view class="title-wrap">
<text class="text">{{title}}</text>
</view>
</view>
</view>
</view>
js
// pages/components/navBar/navBar.js
const { getApi, postApi, imageHost } = require("../../../utils/request")
const app = getApp()
Component({
/**
* 组件的属性列表
*/
properties: {
title: { //标题内容
type: String,
value: ''
},
bgFlag: { //是否背景图
type: Boolean,
value: false
},
back: { //返回按钮是否展示
type: Boolean,
value: false
}
},
/**
* 组件的初始数据
*/
data: {
imageHost,
statusBarHeight: app.globalData.statusBarHeight,//自定义顶部栏高度
headerBarHeight: app.globalData.headerBarHeight
},
/**
* 组件的方法列表
*/
methods: {
onBack() {
wx.navigateBack()
}
},
options: {
addGlobalClass: true
}
})
wxss
/* pages/components/navBar/navBar.wxss */
.nav-bar-box image{
height: 500rpx;
width: 100%;
}
.nav-bar-box .login-com{
position: relative;
}
.nav-bar-box .login-com .title{
position: absolute;
width: 100%;
text-align: center;
font-size: 36rpx;
font-family: 'Source Han Sans CN';
font-weight: 500;
color: #222221;
}
.nav-bar-box .other-com{
width: 100%;
text-align: center;
font-size: 36rpx;
font-family: 'Source Han Sans CN';
font-weight: 500;
color: #222221;
background-color: #BECFAA;
}
.nav-bar-box .other-com .title{
position: relative;
display: flex;
padding: 0 24rpx;
box-sizing: border-box;
display: flex;
}
.nav-bar-box .other-com .icon-wrap{
width: 20px;
}
.nav-bar-box .other-com .icon-wrap .icon{
font-size: 40rpx;
}
.nav-bar-box .other-com .title-wrap{
flex: 1;
width: 1rpx;
text-align: center;
}
.nav-bar-box .other-com .title-wrap .text{
position: relative;
transform: translate(-50%,-50%);
font-size: 36rpx;
font-family: 'Source Han Sans CN';
font-weight: 500;
color: #222221;
}