微信小程序自定义导航栏组件
1.首先,要在json文件中设置为自定义的形式
"navigationStyle": "custom"
2.计算相关值
导航栏分为状态栏和标题栏,只要能算出每台手机的导航栏高度问题就迎刃而解
- 导航栏高度 = 胶囊按钮高度 + 状态栏到胶囊按钮间距 * 2 + 状态栏高度
注:由于胶囊按钮是原生组件,为表现一致,其单位在各种手机中都为 px,所以我们自定义导航栏的单位都必需是 px(切记不能用 rpx),才能完美适配。
因为在不同的手机型号头部那条栏目高度可能不一致,所以为了我们适配更多型号,我们需要计算3个值:
如下图:

1. 整个导航栏的高度;
2. 胶囊按钮与顶部的距离;
3. 胶囊按钮与右侧的距离。
小程序可以通过 wx.getMenuButtonBoundingClientRect() 获取胶囊按钮的信息 和 wx.getSystemInfo() 获取设备信息。
如下图:

通过这些信息我们可以计算出上面说的3个值:
1. 整个导航栏高度 = statausBarHeight + height + (top-statausBarHeight )*2;
2. 胶囊按钮与顶部的距离 = top;
3.胶囊按钮与右侧的距离 = windowWidth - right。
现在我们明白了原理,可以利用胶囊按钮的位置信息和 statusBarHeight 高度动态计算导航栏的高度,贴一个实现此功能最重要的方法
let systemInfo = wx.getSystemInfoSync();
let rect = wx.getMenuButtonBoundingClientRect ? wx.getMenuButtonBoundingClientRect() : null; //胶囊按钮位置信息
wx.getMenuButtonBoundingClientRect();
let navBarHeight = (function() { //导航栏高度
let gap = rect.top - systemInfo.statusBarHeight; //动态计算每台手机状态栏到胶囊按钮间距
return 2 * gap + rect.height;
})();
gap 信息就是不同的手机其状态栏到胶囊按钮间距,具体更多代码实现和使用 demo 请移步下方代码仓库,代码中还会有输入框文字跳动解决办法,安卓手机输入框文字飞出解决办法,左侧按钮边框太粗解决办法等等
App.js 代码如下:
App({
globalData: {
},
onLaunch: function () {
let menuButtonObject = wx.getMenuButtonBoundingClientRect();
wx.getSystemInfo({
success: res => {
let statusBarHeight = res.statusBarHeight,
navTop = menuButtonObject.top,//胶囊按钮与顶部的距离
navHeight = statusBarHeight + menuButtonObject.height + (menuButtonObject.top - statusBarHeight)*2;//导航高度
this.globalData.navHeight = navHeight;
this.globalData.navTop = navTop;
this.globalData.windowHeight = res.windowHeight;
},
fail(err) {
console.log(err);
}
})
}
})
3.因为这个头部导航是公共的,所以我们最好把它设置成一个组件,命名为navbar
index.wxml
<view class="navbar custom-class" style='height:{{navHeight}}px;background-color:{{bgColor}}'>
<view wx:if="{{showNav}}" class="navbar-action-wrap navbar-action-group row item-center" style='top:{{navTop}}px;background-color:rgba(255,255,255,.6)'>
<ss-icon name="back" color="{{iconColor}}" size="15px" block="{{true}}" class="navbar-action_item" bind:click="_navBack"></ss-icon>
<ss-icon name="index" color="{{iconColor}}" size="15px" block="{{true}}" class="navbar-action_item last" bind:click="_toIndex"></ss-icon>
</view>
<view class='navbar-title' style='top:{{navTop}}px'>
{{pageName}}
</view>
</view>
index.js:
// components/navbar/index.js
const App = getApp(); Component({
options: {
addGlobalClass: true,
},
/**
* 组件的属性列表
*/
properties: {
pageName:String,
showNav:{
type:Boolean,
value:true
},
showHome: {
type: Boolean,
value: true
}
}, /**
* 组件的初始数据
*/
data: { },
lifetimes: {
attached: function () {
this.setData({
navH: App.globalData.navHeight
})
}
},
/**
* 组件的方法列表
*/
methods: {
//回退
navBack: function () {
wx.navigateBack({
delta: 1
})
},
//回主页
toIndex: function () {
wx.navigateTo({
url: '/pages/admin/home/index/index'
})
},
}
})
index.wxss:
/* components/navbar/index.wxss */
.navbar {
width: 100%;
overflow: hidden;
position: relative;
top: 0;
left: 0;
z-index: 10;
flex-shrink: 0;
}
.navbar-title {
width: 100%;
box-sizing: border-box;
padding-left: 115px;
padding-right: 115px;
height: 32px;
line-height: 32px;
text-align: center;
position: absolute;
left: 0;
z-index: 10;
color: #333;
font-size: 16px;
font-weight: bold;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.navbar-action-wrap {
display: -webkit-flex;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
-webkit-align-items: center;
align-items: center;
position: absolute;
left: 10px;
z-index: 11;
line-height: 1;
padding-top: 4px;
padding-bottom: 4px;
}
.navbar-action-group {
border: 1px solid #f0f0f0;
border-radius: 20px;
overflow: hidden;
}
.navbar-action_item {
padding: 3px 0;
color: #333;
}
.navbar-action-group .navbar-action_item {
border-right: 1px solid #f0f0f0;
padding: 3px 14px;
}
.navbar-action-group .last {
border-right: none;
}
index.json:
{
"component": true,
"usingComponents": {
"ss-icon": "../icon/index"
}
}
组件已创建完毕,现在说下该组件的使用方法:
假设我们需要在index.wxml中需要调用这个组件,
1.在index.json中引用该组件:
{
"usingComponents": {
"navbar": "/components/navbar/index"
}
}
2.在index.wxml中使用该组件:
<view class='view-page'>
<navbar page-name="你当前页面的名字"></navbar>
<view class='page-content'>
<!--这里放你的内容-->
</view>
</view>
最后的结果如下图所示:

3.参数说明

胶囊信息报错和获取不到
问题就在于 getMenuButtonBoundingClientRect 这个方法,在某些机子和环境下会报错或者获取不到,对于此种情况完美可以模拟一个胶囊位置出来
try {
rect = Taro.getMenuButtonBoundingClientRect ? Taro.getMenuButtonBoundingClientRect() : null;
if (rect === null) {
throw 'getMenuButtonBoundingClientRect error';
}
//取值为0的情况
if (!rect.width) {
throw 'getMenuButtonBoundingClientRect error';
}
//取值为0的情况
if (!rect.width) {
throw 'getMenuButtonBoundingClientRect error';
}
} catch (error) {
let gap = ''; //胶囊按钮上下间距 使导航内容居中
let width = 96; //胶囊的宽度,android大部分96,ios为88
if (systemInfo.platform === 'android') {
gap = 8;
width = 96;
} else if (systemInfo.platform === 'devtools') {
if (ios) {
gap = 5.5; //开发工具中ios手机
} else {
gap = 7.5; //开发工具中android和其他手机
}
} else {
gap = 4;
width = 88;
}
if (!systemInfo.statusBarHeight) {
//开启wifi的情况下修复statusBarHeight值获取不到
systemInfo.statusBarHeight = systemInfo.screenHeight - systemInfo.windowHeight - 20;
}
rect = {
//获取不到胶囊信息就自定义重置一个
bottom: systemInfo.statusBarHeight + gap + 32,
height: 32,
left: systemInfo.windowWidth - width - 10,
right: systemInfo.windowWidth - 10,
top: systemInfo.statusBarHeight + gap,
width: width
};
console.log('error', error);
console.log('rect', rect);
}
还有一种写法是胶囊按钮那部分的高度设置为40,导航栏的高度用动态的头加上40
参考1: https://www.cnblogs.com/sese/p/9761713.html
参考2: https://juejin.im/post/6844903916963004423
微信小程序自定义导航栏组件的更多相关文章
- 微信小程序自定义导航栏组件,完美适配所有手机,可实现各种功能和情况
背景 在做小程序时,关于默认导航栏,我们遇到了以下的问题: Android.IOS 手机对于页面 title 的展示不一致,安卓 title 的显示不居中 页面的 title 只支持纯文本级别的样式控 ...
- 微信小程序——自定义导航栏
微信头部导航栏可能通过json配置: 但是有时候我们项目需求可能需要自定义头部导航栏,如下图所示: 现在具体说一下实现步骤及方法: 步骤: 1.在 app.json 里面把 "navigat ...
- 微信小程序自定义导航栏
微信小程序需要自定义导航栏,特别是左上角的自定义设置,可以设置返回按钮,菜单按钮,配置如下: 1.在app.json的window属性中增加: navigationStyle:custom 顶部导航栏 ...
- 微信小程序 - 自定义导航栏(提示)
点击下载: 自定义导航栏示例
- 微信小程序 自定义导航组件 nav头部 全面屏设计
nav-dynamic 微信小程序自定义nav头部组件:适配全面屏设计: 实现功能 初始进入页面时,展示初始状态下的nav样式: 页面滚动时,监听页面滚动事件,展示滚动状态下的nav样式: 根据配置字 ...
- 获取不同机型微信小程序状态栏+导航栏高度
获取不同机型微信小程序状态栏+导航栏高度 一. 前言 很多时候我们开发微信小程序,都需要先知道状态栏和导航栏的高度,才能去做其他功能 二. 获取微信小程序状态栏高度 用wx.getSystemInfo ...
- Taro 小程序 自定义导航栏
在小程序中,有的页面需求可能需要我们做一个自定义的导航栏, 今天就来踩一踩坑 首先需要在app.js 中给全局的导航栏隐藏, // app.js window: { navigationStyle: ...
- 微信小程序底部导航栏部署
在微信小程序开发app.json(app.json它是定义全局页面) 只是用来部署微信底部的图标,最多不能大于五个 "tabBar":{ "selectedColor&q ...
- 微信小程序底部导航栏(tabbar)
在app.json处设置“tabBar”,例子如下: { "pages": [ "pages/index/index", "pages/pages1/ ...
随机推荐
- Docker(4)-docker常用命令
帮助命令 docker version # 查看docker的版本信息 docker info # 查看docker的系统信息,包含镜像和容器的数量 docker --help # 帮助命令 dock ...
- C++内存管理:简易内存池的实现
什么是内存池? 在上一篇 C++内存管理:new / delete 和 cookie中谈到,频繁的调用 malloc 会影响运行效率以及产生额外的 cookie, 而内存池的思想是预先申请一大块内存, ...
- 学习 27 门编程语言的长处,提升你的 Python 代码水平
Python猫注:Python 语言诞生 30 年了,如今的发展势头可谓如火如荼,这很大程度上得益于其易学易用的优秀设计,而不可否认的是,Python 从其它语言中偷师了不少.本文作者是一名资深的核心 ...
- 解决android studio no debuggable process
这个问题可能是由多种因素造成的. 一.可能是buildtypes配置或选择错误,在对应module的build.gradle中确认如下配置 debug { debuggable true//一定要配置 ...
- c++内存分布之虚函数(单一继承)
系列 c++内存分布之虚函数(单一继承) [本文] c++内存分布之虚函数(多继承) 结论 1.虚函数表指针 和 虚函数表 1.1 影响虚函数表指针个数的因素只和派生类的父类个数有关.多一个父类,派生 ...
- 惊!世界上竟然有O(N)时间复杂度的排序算法!计数排序!
啥?你以为排序算法的时间复杂度最快也只能O(N*log(N))了? O(N)时间复杂度的排序算法听说过没有?计数排序!!它是世界上最快最简单的算法!!! 计数排序算法操作起来只有三步,看完秒懂! 根据 ...
- 【LeetCode】1102. Path With Maximum Minimum Value 解题报告 (C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 排序+并查集 优先级队列 日期 题目地址:https: ...
- 【LeetCode】217. Contains Duplicate 解题报告(Java & Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 字典统计词频 使用set 排序 日期 [LeetCo ...
- 【LeetCode】22. Generate Parentheses 括号生成
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 个人公众号:负雪明烛 本文关键词:括号, 括号生成,题解,leetcode, 力扣,Pyt ...
- 【LeetCode】17. Letter Combinations of a Phone Number 电话号码的字母组合
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 个人公众号:负雪明烛 本文关键词:电话号码, 字母组合,回溯法,题解,leetcode, ...