前言
世界之大无奇不有,当客户对于导航栏不满时候,就需要我们自己去开发了。当然uniapp也有很多自定义导航插件,但现在我们要自己写。
首先,我们要知道有那几部分。
可以看到在我们的,这个时候我们自定义的导航栏,需要做到标题于胶囊水平对齐,那其实这个时候整个头部其实主要又:。
上图中,微信小程序中,头部导航栏其实受到右上角胶囊的限制比较大,也就需要我们做改进,我们可以看到:状态栏的高度+标题栏的高度组成。
状态栏的高度我们可以通过uni.getSystemInfoSync().statusBarHeight来获取。
现在要如何获取标题栏?
如果想要定义标题栏的高度,就要锁定这个胶囊的位置,在小程序中我们可以使用wx.getMenuButtonBoundingClientRect()获取关于胶囊的信息
获取到的胶囊的top,left,right分别对应胶囊的上边界,左边界,右边界相对于屏幕左上角的起点的位置,现在=就来说说我们要怎么修改处理(胶囊上边界距离顶部的距离 - 状态栏的高度)*2+胶囊的高度,就是标题栏的高度呢?然后再在标题栏里面添加一个文本区让他的高度等于胶囊的高度,实现flex布局的上下居中是不是就搞定了呢?
在使用uniapp中,要考虑到多端情况。
在使用uniapp获取到的状态栏在h5,小程序和app原生都是有效的,h5网页中一般就可以直接采用浏览器内核给我们内置的网页导航栏,就是一个头部,没有过多的要求,而且浏览器不同,给我们提供的头部导航也不一样。
而对于app端,我们没有了像微信小程序中那种让人心烦的胶囊之后,我们只需要知道状态栏的高度,然后加上自己业务需求的标题栏样式和标题栏高度就行啦。
所以我们在进行自定义导航栏封装的时候就要对代码进行条件编译啦。那么我这里呢是把微信小程序做了多带带的处理,微信小程序之外的平台看作是统一状态。
献上源码:
首先我们把获取设备信息的代码封装到一个统一的js文件里面,这样方便我们在组件中获取也方便我们在页面中获取。
/**
* 此js文件管理关于当前设备的机型系统信息
const systemInfo = function() {
/****************** 所有平台共有的系统信息 ********************/
// 设备系统信息
let systemInfomations = uni.getSystemInfoSync()
// 机型适配比例系数
let scaleFactor = 750 / systemInfomations.windowWidth
// 当前机型-屏幕高度
let windowHeight = systemInfomations.windowHeight * scaleFactor //rpx
// 当前机型-屏幕宽度
let windowWidth = systemInfomations.windowWidth * scaleFactor //rpx
// 状态栏高度
let statusBarHeight = (systemInfomations.statusBarHeight) * scaleFactor //rpx
// 导航栏高度 注意:此导航栏高度只针对微信小程序有效 其他平台如自定义导航栏请使用:状态栏高度+自定义文本高度
let navHeight = 0 //rpx
// console.log(windowHeight,'哈哈哈哈哈');
/****************** 微信小程序头部胶囊信息 ********************/
// #ifdef MP-WEIXIN
const menuButtonInfo = wx.getMenuButtonBoundingClientRect()
// 胶囊高度
let menuButtonHeight = menuButtonInfo.height * scaleFactor //rpx
// 胶囊宽度
let menuButtonWidth = menuButtonInfo.width * scaleFactor //rpx
// 胶囊上边界的坐标
let menuButtonTop = menuButtonInfo.top * scaleFactor //rpx
// 胶囊右边界的坐标
let menuButtonRight = menuButtonInfo.right * scaleFactor //rpx
// 胶囊下边界的坐标
let menuButtonBottom = menuButtonInfo.bottom * scaleFactor //rpx
// 胶囊左边界的坐标
let menuButtonLeft = menuButtonInfo.left * scaleFactor //rpx
// 微信小程序中导航栏高度 = 胶囊高度 + (顶部距离 - 状态栏高度) * 2
navHeight = menuButtonHeight + (menuButtonTop - statusBarHeight) * 2
// #endif
// #ifdef MP-WEIXIN
return {
scaleFactor,
windowHeight,
windowWidth,
statusBarHeight,
menuButtonHeight,
menuButtonWidth,
menuButtonTop,
menuButtonRight,
menuButtonBottom,
menuButtonLeft,
navHeight
// #endif
// #ifndef MP-WEIXIN
return {
scaleFactor,
windowHeight,
windowWidth,
statusBarHeight
// #endif
export {
systemInfo
}
然后我们定义一个导航栏组件
/*
*1、在传入宽度或者高度时,如果是Number数据,传入的值为px大小,无需带单位,组件自动计算
*2、在使用此导航栏时,建议传入UI规定的导航栏高度,此高度只针对除微信小程序的其他平台有效,微信小程序的导航栏高度,组件自计算
<template>
<view>
<!--微信小程序头部导航栏-->
<!--#ifdef MP-WEIXIN-->
<view class="wx-head-mod":style="{height:navHeight+'rpx',backgroundColor:navBackgroundColor}">
<view class="wx-head-mod-nav":style="{height:navigationBarHeight+'rpx',top:statusBarHeight+'rpx'}">
<view class="wx-head-mod-nav-content"
:style="{height:customHeight+'rpx',justifyContent:textAlign==='center'?'center':'left'}">
<!--文本区-->
<view class="wx-head-mod-nav-content-mian"
:style="{width:navTextWidth,lineHeight:customHeight+'rpx',paddingLeft:textPaddingLeft*scaleFactor+'rpx',fontSize:fontSize*scaleFactor+'rpx',fontWeight:fontWeight,color:titleColor}">
{{textContent}}
</view>
<!--返回按钮-->
<view class="wx-head-mod-nav-content-back":style="{display:isBackShow?'flex':'none'}"
click="backEvent">
<view class="wx-head-mod-nav-content-back-img"
:style="{width:backImageWidth*scaleFactor+'rpx',height:backImageHeight*scaleFactor+'rpx'}">
<image:src="backImageUrl"mode=""style="width:100%;height:100%;"></image>
</view>
</view>
</view>
</view>
</view>
<!--#endif-->
<!--除微信小程序之外的其他设备-->
<!--#ifndef MP-WEIXIN-->
<view class="other-head-mod"
:style="{height:navHeightValue*scaleFactor+statusBarHeight+'rpx',backgroundColor:navBackgroundColor}">
<view class="other-head-mod-mian"
:style="{height:navHeightValue*scaleFactor+'rpx',justifyContent:textAlign==='center'?'center':'left'}">
<!--返回按钮-->
<view class="other-head-mod-mian-back"v-show="isBackShow" click="backEvent">
<view class="other-head-mod-mian-back-img"
:style="{width:backImageWidth*scaleFactor+'rpx',height:backImageHeight*scaleFactor+'rpx'}">
<image:src="backImageUrl"mode=""style="width:100%;height:100%;"></image>
</view>
</view>
<!--标题-->
<view class="other-head-mod-mian-title":style="{width:windowWidth-184+'rpx',lineHeight:navHeightValue*scaleFactor+'rpx',
paddingLeft:textPaddingLeft*scaleFactor+'rpx',fontSize:fontSize*scaleFactor+'rpx',
fontWeight:fontWeight,color:titleColor}">
{{textContent}}
</view>
</view>
</view>
<!--#endif-->
</view>
</template>
<script>
const app=getApp()
import{systemInfo}from' /common/system-info.js'
export default{
name:"HeadView",
props:{
//文本区域位置left:左center:中
textAlign:{
type:String,
default:'center'
//文本区内容
textContent:{
type:String,
default:'哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈就啊哈哈好借好还'
//文本区离左边的距离
textPaddingLeft:{
type:Number,
default:16
//是否需要返回按钮
isBackShow:{
type:Boolean,
default:true
//文本区字体大小
fontSize:{
type:Number,
default:20//px
//文本区字体粗细
fontWeight:{
type:Number,
default:700
//文本区返回按钮图片宽
backImageWidth:{
type:Number,
default:12//px
//文本区返回按钮图片高
backImageHeight:{
type:Number,
default:24//px
//返回按钮图标路径
backImageUrl:{
type:String,
default:'/static/backImage.svg'
//导航栏整体背景颜色
navBackgroundColor:{
type:String,
default:'#2476F9'
//标题字体颜色
titleColor:{
type:String,
default:'#ffffff',
/********h5端,app端需要传入自定义导航栏高度*******/
navHeightValue:{
type:Number,
default:44//px
computed:{
//文本区宽度
navTextWidth(){
if(this.textAlign==='center'){
return(this.windowWidth-(this.windowWidth-this.menubarLeft)*2)+'rpx'
}else{
return this.menubarLeft+'rpx'
//文本区paddingLeft
textPaddingleft(){
if(this.textAlign==='center'){
return'0'
}else{
return this.textPaddingLeft+'rpx'
data(){
return{
statusBarHeight:app.globalData.statusBarHeight,//状态栏高度
navHeight:app.globalData.navHeight,//头部导航栏总体高度
navigationBarHeight:app.globalData.navigationBarHeight,//导航栏高度
customHeight:app.globalData.customHeight,//胶囊高度
scaleFactor:app.globalData.scaleFactor,//比例系数
menubarLeft:app.globalData.menubarLeft,//胶囊定位的左边left
windowWidth:app.globalData.windowWidth*app.globalData.scaleFactor
methods:{
backEvent(){
uni.navigateBack({
delta:1
created(){
/*获取设备信息*/
const SystemInfomations=systemInfo()
/*通用平台*/
this.statusBarHeight=SystemInfomations.statusBarHeight//状态栏高度
this.scaleFactor=SystemInfomations.scaleFactor//比例系数
this.windowWidth=SystemInfomations.windowWidth//当前设备的屏幕宽度
/*微信小程序平台*/
//#ifdef MP-WEIXIN
this.navHeight=SystemInfomations.navHeight+SystemInfomations.statusBarHeight//头部导航栏总高度
this.navigationBarHeight=SystemInfomations.navHeight//头部导航栏高度
this.customHeight=SystemInfomations.menuButtonHeight//胶囊高度
this.menubarLeft=SystemInfomations.menuButtonLeft//胶囊左边界距离左上角的距离
//#endif
</script>
<style>
/*#ifdef MP-WEIXIN*/
.wx-head-mod{
box-sizing:border-box;
width:100%;
position:fixed;
top:0;
left:0;
.wx-head-mod-nav{
box-sizing:border-box;
width:100%;
left:0;
display:flex;
justify-content:center;
align-items:center;
.wx-head-mod-nav-content{
box-sizing:border-box;
width:100%;
display:flex;
justify-content:left;
align-items:center;
position:relative;
/*文本区*/
.wx-head-mod-nav-content-mian{
box-sizing:border-box;
height:100%;
white-space:nowrap;
text-overflow:ellipsis;
overflow:hidden;
/*返回按钮*/
.wx-head-mod-nav-content-back{
box-sizing:border-box;
width:60rpx;
height:100%;
/*background-color:aqua;*/
top:0;
left:32rpx;
display:flex;
align-items:center;
justify-content:left;
.wx-head-mod-nav-content-back-img{
box-sizing:border-box;
/*#endif*/
/*#ifndef MP-WEIXIN*/
.other-head-mod{
box-sizing:border-box;
width:100%;
position:fixed;
top:0;
left:0;
.other-head-mod-mian{
box-sizing:border-box;
width:100%;
display:flex;
align-items:center;
justify-content:left;
left:0;
bottom:0;
/*返回按钮*/
.other-head-mod-mian-back{
box-sizing:border-box;
height:100%;
width:60rpx;
left:32rpx;
top:0;
display:flex;
align-items:center;
/*标题*/
.other-head-mod-mian-title{
box-sizing:border-box;
height:100%;
white-space:nowrap;
text-overflow:ellipsis;
overflow:hidden;
/*#endif*/
</style>
组件使用:
引入组件:
import HeadNav from' /components/HeadNav.vue'
组册组件:
components:{
HeadNav
},
<template>
<view class="content">
<head-nav></head-nav>
<view class="content-main"></view>
</view>
</template>
效果图:
微信小程序:
h5:
app:
在项目里面没有针对h5时候需要导航栏做特别的限制,如果实际开发中在h5端不需要此导航栏,请在模版上面针对h5页面加入条件编译即可。
欢迎大家继续学习,关注后续更多精彩内容。