自定义导航栏
学习小程序的过程中,发现原生导航栏的确不是特别美观,并且功能比较单一。
通过查看官方文档发现可以自定义导航栏,经过充分调研后,开始定义自己的导航组件。
经过测试,刘海屏也完美兼容,先来看一下最终效果。
普通屏幕:
刘海屏:
1. 全局缓存系统和右侧按钮信息
在app.js中缓存当前系统信息和菜单按钮位置信息。
getSystemInfo:获取系统信息,包括设备品牌、型号,状态栏高度等;
getMenuButtonBoundingClientRect:获取菜单按钮的布局位置信息;
App({
onLaunch () {
wx.getSystemInfo({
success: (res) => {
this.cache.systemInfo = res;
}
})
this.cache.headerPos = wx.getMenuButtonBoundingClientRect();
},
cache: {
systemInfo: {}, // 系统信息
headerPos: {} // 按钮位置信息
}
})
获取到相关位置信息,将信息缓存到cache对象中,以备后续使用。
2. components文件夹下建立navbar组件
目录结构如下:
编写布局和样式文件
由于需要对不同设备进行兼容,不能使用默认高度,需要根据当前系统信息和菜单按钮信息进行计算,单位统一使用px。
导航栏分为两部分,一部分是导航栏,一部分是空白的占位盒子。
因为导航栏使用fixed定位,所有会脱离文档流,主体内容会上移,所以使用一个空白盒子进行占位,高度和导航栏一致。
导航栏分为文字部分和图标部分,高度和位置进行动态赋值。
文字设置居中显示,图标设置fiexed定位。
navbar.wxml
<view
class="navbar"
style="height: {{ navbarHeight }}px; padding-top: {{ statusBarHeight }}px;"
>
<view
wx:if="{{ showIcon }}"
class="navbar-icon"
style="top: {{ navbarPos.top + statusBarHeight }}px; left: {{ navbarPos.right }}px; height: {{ navbarPos.height }}px; width: {{ navbarPos.width }}px;"
>
<image
wx:if="{{ hasBack }}"
class="left-arrow-img"
src="/images/icon/left-arrow.png"
catchtap="backBtnClick"
/>
<image
class="home-img"
src="/images/icon/home.png"
catchtap="homeBtnClick"
/>
</view>
<view
class="navbar-title"
style="line-height: {{ navbarPos.height + navbarPos.top }}px;"
>
<text>{{ title }}</text>
</view>
</view>
<view
style="height: {{ navbarHeight }}px; line-height: {{navbarHeight}}px;"
></view>
navbar.wxss
.navbar {
position: fixed;
width: 100%;
top: 0;
left: 0;
z-index: 999;
box-sizing: border-box;
background-color: rgba(255, 250, 250, .9);
}
.navbar .navbar-icon {
position: fixed;
display: flex;
justify-content: space-evenly;
align-items: center;
border-radius: 35rpx;
border: .5rpx solid rgba(248, 248, 255, .9);
box-sizing: border-box;
}
.navbar .navbar-icon .home-img,
.navbar .navbar-icon .left-arrow-img {
width: 45rpx;
height: 45rpx;
padding-right: 5rpx;
}
.navbar .navbar-title {
padding-top: 5rpx;
text-align: center;
font-weight: 600;
font-size: 35rpx;
color: #000;
}
3. navbar.js文件编写
左侧自定义图标及回调按钮位置,依靠状态栏高度和菜单按钮的位置信息计算。
状态栏高度:app.cache.systemInfo.statusBarHeight
自定义菜单按钮坐标:
1. 上边距:菜单按钮上边界坐标 - 状态栏高度
2. 右边距:屏幕宽度 - 菜单按钮右边界坐标
3. 下边距:菜单按钮下边界坐标 - 菜单按钮高度 - 状态栏高度
4. 导航栏高度:菜单按钮下边界坐标 + 下边距
注意点:
菜单按钮下边界坐标是包括状态栏、菜单按钮高度和菜单按钮高度之间的距离的,菜单按钮居中在导航栏中,所以上边距和下边距应该一致,所以菜单下边距应该是菜单按钮下边界坐标 - 菜单按钮高度 - 状态栏高度。
const app = getApp();
Component({
properties: {
title: String,
showIcon: {
type: Boolean,
value: true
}
},
data: {
hasBack: true,
statusBarHeight: 0,
navbarHeight: 0,
navbarPos: {
height: 0,
width: 0,
top: 0,
right: 0,
bottom: 0,
left: 0
}
},
attached () {
const { statusBarHeight, screenWidth } = app.cache.systemInfo,
{ headerPos } = app.cache;
const navbarPos = {
height: headerPos.height,
width: headerPos.width,
top: headerPos.top - statusBarHeight,
bottom: headerPos.bottom - headerPos.height - statusBarHeight,
right: screenWidth - headerPos.right
}
const hasBack = getCurrentPages().length === 1 ? false : true;
this.setData({
hasBack,
statusBarHeight,
navbarHeight: headerPos.bottom + navbarPos.bottom,
navbarPos
})
},
methods: {
backBtnClick () {
wx.navigateBack({
delta: 1
});
},
homeBtnClick () {
wx.redirectTo({
url: '/pages/index/index'
});
}
}
})
主要逻辑在attched函数中,此函数是小程序自定义组件的生命周期钩子函数。将计算后的navbarPos赋值给data对象,供页面使用。
此外还使用getCurrentPages().length获取当前路由栈的长度,如果长度等于1,说明不是由路由跳转过来,就隐藏回退按钮的图标,默认都显示。
还可以配置showIcon来切换自定义图标的显示和隐藏。
4. 首页使用自定义导航栏组件
配置index.json文件
通过usingComponents引入navbar组件,配置navigationStyle为自定义(custom)。
{
"usingComponents": {
"common-header": "/components/header/common/common",
"navbar": "/components/navbar/navbar"
},
"navigationStyle": "custom"
}
index.wxml 使用导航栏组件
在页面顶部使用navbar组件,传入参数title和showIcon。
<navbar
title="悦音乐"
showIcon="{{ false }}"
/>
5. 总结
本次自定义组件样式比较简单,如果需要更加复杂的样式和效果,可以根据这个案例进行进一步的拓展,实现自己的业务需求。