前言
世界之大无奇不有,当客户对于导航栏不满时候,就需要我们自己去开发了。当然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%;
position:absolute;
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;*/
position:absolute;
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;
position:absolute;
left:0;
bottom:0;
}
/*返回按钮*/
.other-head-mod-mian-back{
box-sizing:border-box;
height:100%;
width:60rpx;
position:absolute;
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页面加入条件编译即可。
欢迎大家继续学习,关注后续更多精彩内容。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/128381.html
摘要:官方资料微信公众平台注册小程序。官网开发文档社区开发工具部署微信小程序微信小程序本身不需要部署,在微信开发工具中直接上传代码就行。 为什么 学习 Java 三年,目前已经工作了2年,因为自学,基础差,所以打算年末总结一下常见的基础知识和面试点; 也可以通过独立做一个项目整合自己工作期间学习的知识,加深印象。 但是想着回家或是平时手机用的多,做一款APP和小程序很方便查看。 项目展示 本...
摘要:本次测试主要参考文档为选择器参考手册主要是安卓微信小程序的选择器兼容入坑小程序过程中看到微信对支持的选择器的描述只有六个分别是但是看到给写的花里胡哨的的库还有各种花里胡哨的小程序并且还表明支持之前各种无的库所以我觉得事情并没有这么简单趁着元 本次测试主要参考文档为w3school CSS 选择器参考手册 (主要是安卓/ios/微信小程序的css选择器兼容) 入坑uniapp/小程序过...
摘要:最近在捣鼓项目,恰好用到组件,之前写了个,后面一直都想写一个像样的,可以分享给别人用的组件。自己的水平一般,开发出来的组件可能代码不咋地,还望路过大神斧正。 uniapp是2019年非常的火爆的一个Dcloud开发跨平台前端工具,支持ios android wap,小程序,除了android有点卡外,其他暂时没有发现什么瑕疵。 最近在捣鼓uniapp项目,恰好用到table组件,之前...
摘要:配置配置全解析项目配置文件文件描述项目配置文件项目代码配置是否检查域名安全性和版本是否将项目的代码转成是否自动补全兼容前缀是否压缩代码是否启用新功能编译方式版本号项目名项目配置搜索关键字客服编译方式小程序配置项目路由设置第一项为首页窗 1. 配置 配置全解析 project.config.json ( 项目配置文件 ) { // 文件描述 description: 项目...
阅读 842·2023-03-27 18:33
阅读 1095·2023-03-26 17:27
阅读 999·2023-03-26 17:14
阅读 911·2023-03-17 21:13
阅读 845·2023-03-17 08:28
阅读 2429·2023-02-27 22:32
阅读 1763·2023-02-27 22:27
阅读 2790·2023-01-20 08:28