小程序自定义顶部导航栏
上篇博客自定义了一个底部导航栏,效果还可以,但是我在开发过程中又遇到了一个棘手的问题。就是在底部导航栏的第一个页面需要将页面沉浸到状态栏去,这就麻烦了,因为中间的容器页面无论第几个都是在外面的主界面里,而主界面需要动态的去隐藏标题栏,设计师这是在为难我胖虎?
当然也不是没有办法,这里就需要用到自定义的导航栏了,下面详细介绍。
先看效果
这个是首页的沉浸状态栏效果
这个是非首页的标题栏效果
看看代码
- WXML
<!--pages/tabbar/index.wxml-->
<cover-view wx:if="{{!isStatusBar}}" style="height:{{topHeight}}rpx;background:white;">
<cover-view class="center-both" style="margin-top:{{statusHeight}}rpx;height: {{naviHeight}}rpx">
<cover-view>
{{title}}
</cover-view>
</cover-view>
</cover-view>
<view class="page-container" style="height:{{containerHeight}}rpx">
<!-- 使用wx:if 不会渲染,每次点击会重走组件生命周期 -->
<!-- 使用display:none隐藏,仍然会渲染组件,只走一遍生命周期 -->
<!-- 使用hidden隐藏,和display:none一样,但是受限于块级元素,无法使用 -->
<!-- 用户 -->
<block wx:if="{{roleType=='user'}}">
<home id="id0" indexpage="{{true}}" style="display: {{currentPageIndex==0?'block':'none'}};" />
<user id="id1" show='{{currentPageIndex==1}}' style="display: {{currentPageIndex==1?'block':'none'}};" />
</block>
<!-- 管理员 -->
<block wx:elif="{{roleType=='manager'}}">
<manager id="id0" style="display: {{currentPageIndex==0?'block':'none'}};" />
<log id="id1" style="display: {{currentPageIndex==1?'block':'none'}};" />
</block>
</view>
<!-- 底部切换菜单 -->
<view class="row-center tab-container" style="height:{{104 + bottomHeight}}rpx;padding-bottom:{{bottomHeight}}rpx">
<view wx:for="{{tabBar}}" wx:key="index" class="flex1 center-both col"
style="color:{{index==currentPageIndex?'#0B7BFBFF':'#616161FF'}}" data-index="{{index}}" bindtap="onSelectTap">
<view class="{{item.iconClass}} icon"></view>
<view class="text">{{item.text}}</view>
</view>
</view>
在昨天的基础上加了自定义的顶部导航栏,适配了一下高度,使用 cover-view 放在了最顶层。
- WXSS
这里没什么变化,导航栏样式直接写在 style 里了,需要的话可以写在 wxss 里。
- JSON
{
"navigationStyle": "custom",
...
}
配置文件里面加入上面这句话,自定义导航栏,需要微信客户端7.0支持,如果要适配的话可以去全局的 windows 里面设置。
- Page.js
// pages/index/index.js
var app = getApp()
Page({
data: {
//状态栏高度
statusHeight: app.globalData.statusHeight,
//导航栏高度
naviHeight: app.globalData.naviHeight,
//顶部高度 = 状态栏高度 + 导航栏高度
topHeight: app.globalData.topHeight,
//底部高度
bottomHeight: app.globalData.bottomHeight,
//中间内容容器高度 = 屏幕高度 - 底部安全高度 - 底部导航栏高度
containerHeight: app.globalData.screenHeight - app.globalData.bottomHeight - 104,
isStatusBar: true,
title: '',
currentPageIndex: 0,
roleType: "",
tabBar: [],
userTabBar: [{
"iconClass": "iconfont home",
"text": "首页",
"uptoStatus": true
},
{
"iconClass": "iconfont user",
"text": "个人中心",
"uptoStatus": false
},
],
managerTabBar: [{
"iconClass": "iconfont manager",
"text": "管理",
"uptoStatus": false
},
{
"iconClass": "iconfont log",
"text": "日志",
"uptoStatus": false
},
]
},
onLoad: function (options) {
let tabBar = this.data.tabBar
if (options.roleType == 'user') {
tabBar = this.data.userTabBar
} else if (options.roleType == 'manager') {
tabBar = this.data.managerTabBar
}
// 在此加载数据
this.setData({
tabBar: tabBar,
roleType: options.roleType,
})
},
// 下拉加载
onPullDownRefresh() {
this.selectComponent("#id" + this.data.currentPageIndex).onPullDownRefresh()
},
onSelectTap(event) {
let index = event.currentTarget.dataset.index;
let isStatusBar = this.data.tabBar[index].uptoStatus;
//中间页面高度 = 屏幕高度 - 底部安全高度 - 底部导航高度 - 顶部高度
let containerHeight = app.globalData.screenHeight - bottomHeight - 104
if (!isStatusBar) {
containerHeight = containerHeight - this.data.topHeight
}
//选中页面更新
this.setData({
currentPageIndex: index,
title: this.data.tabBar[index].text,
currentPageIndex: index,
isStatusBar: isStatusBar,
containerHeight: containerHeight
})
},
})
Page中的改动就多了点,一个一个讲吧。
先引入了顶部导航栏适配需要用到的三个变量,状态栏高度、标题栏高度以及两者之和,标题栏使用 margin 在状态栏空出对应高度,再使用居中对齐使标题居中,适配效果不错。
同时引入是否沉浸状态栏和标题两个变量,isStatusBar控制是否显示顶部导航栏,标题就不用说了。
在各个标签信息里面增加了 uptoStatus 字段,确定是否要沉浸状态栏。
最后就是切换页面中,要判断选中页面是否要沉浸状态栏,如果要沉浸状态栏,还得修改中间容器的高度,同时标题也应该对应修改。
适配数据
这里也把高度适配数据贴一份吧,具体解释看前面博客。
globalData: {
//系统信息
systemInfo: {},
//1px像素值 对应 rpx
pixelRatio1: 2,
//胶囊信息
menuInfo: {},
//屏幕高度
screenHeight: 2000,
//顶部高度 = 状态栏高度 + 导航栏高度
topHeight: 0,
//状态栏高度
statusHeight: 0,
//导航栏高度
naviHeight: 0,
//底部安全高度
bottomHeight: 0,
},
onLaunch: function () {
var that = this;
//获取设备信息
let systemInfo = wx.getSystemInfoSync()
that.globalData.systemInfo = systemInfo
//1rpx 像素值
let pixelRatio1 = 750 / systemInfo.windowWidth;
that.globalData.pixelRatio1 = pixelRatio1
//胶囊信息
let menu = wx.getMenuButtonBoundingClientRect()
that.globalData.menuInfo = menu
//状态栏高度
let statusHeight = systemInfo.statusBarHeight
that.globalData.statusHeight = statusHeight * pixelRatio1
//导航栏高度
let naviHeight = (menu.top - statusHeight) * 2 + menu.height
that.globalData.naviHeight = naviHeight * pixelRatio1
//顶部高度 = 状态栏高度 + 导航栏高度
that.globalData.topHeight = (statusHeight + naviHeight) * pixelRatio1
//屏幕高度
let screenHeight = systemInfo.screenHeight
that.globalData.screenHeight = screenHeight * pixelRatio1
//底部高度 = 屏幕高度 - 安全区域bottom
let bottom = systemInfo.safeArea.bottom
that.globalData.bottomHeight = (screenHeight - bottom) * pixelRatio1
}
结语
顶部导航栏自定义起来还是挺简单的,就是这里也有一些不如意的问题,比如在苹果手机上使用,可以一直上拉,让标题栏都划上去,但是在安卓使没问题的,机型问题就不管了,有机会调。
end
完美撒花
转载自:https://juejin.cn/post/7222862599851556921