微信小程序自定义导航栏(模板化)

作者:刘家军 时间:2024-10-12 03:50:44 

前段时间写过一篇关于微信小程序自定义导航栏的自定义组件,但是对于分享页有一定的bug
这次用模板化又搞了一遍 优化了下Android与IOS 显示更接近微信原生的导航栏,以及修复分享页面不显示返回首页按钮
如果大家不习惯模板化的话可以 针对自己的需求拿以前封装的组件化做一些修改
微信小程序自定义导航栏(组件化)

CustomNavBar.wxml


<template name="CustomNavBar">
<block wx:if="{{ showNavBar }}">

<!-- 自定义导航栏悬浮时,卡空行 -->
<block wx:if="{{ needFixed }}">
 <view style="position: relative; width: 100%; height: {{ navHeight }}px;"></view>
</block>

<view class="custom-navbar-con relative {{ iOS ? ' ios ' : ' android ' }}" style="height: {{ navHeight }}px; {{ needFixed ? 'position: fixed; top: 0;' : '' }}">
 <view class="custom-navbar-statusbar-con relative" style="height: {{ statusBarHeight }}px;"></view>
 <view class="custom-navbar-content relative" style="height: {{ navHeight - statusBarHeight }}px;">

<!-- iOS端的导航栏显示方式 -->
 <block wx:if="{{ navTitle && navTitle.length > 0 }}">
  <view class="custom-navbar-title ios">{{ navTitle }}</view>
 </block>

<block wx:if="{{ showLeftMenu }}">
  <view class="custom-navbar-left-menu-con clearfix" style="top: {{ navRightMenuRect.top - statusBarHeight - 1 }}px; left: {{ winWidth - navRightMenuRect.right }}px; height: {{ navRightMenuRect.height + 2 }}px;">
  <block wx:if="{{ showBackBtn }}">
   <view class="custom-navbar-icon-btn pull-left back" style="height: {{ navRightMenuRect.height }}px" bindtap="customNavBarBack">
   <image class="icon" src="../../image/icon-nav-back.png" mode="aspectFit" style="width: {{ navRightMenuRect.height }}px;" />
   <text class="text"></text>
   </view>
  </block>

<block wx:if="{{ showHomeBtn }}">
   <view class="custom-navbar-icon-btn pull-left home" style="height: {{ navRightMenuRect.height }}px" bindtap="customNavBarBackToHome">
   <image class="icon" src="../../image/icon-nav-home.png" mode="aspectFit" style="width: {{ navRightMenuRect.height }}px;" />
   <text class="text"></text>
   </view>
  </block>

<!-- android端的导航栏显示方式 -->
  <block wx:if="{{ navTitle && navTitle.length > 0 }}">
   <view class="custom-navbar-title android pull-left" style="line-height: {{ navRightMenuRect.height - 2 }}px;">{{ navTitle }}</view>
  </block>
  </view>
 </block>
 </view>
</view>
</block>
</template>

CustomNavBar.wxss


.custom-navbar-con { position: relative; width: 100%; background-color: white; z-index: 9999; }
.custom-navbar-con .custom-navbar-statusbar-con { width: 100%; }
.custom-navbar-con .custom-navbar-content { width: 100%; }
.custom-navbar-con .custom-navbar-left-menu-con { position: absolute; }
.custom-navbar-con .custom-navbar-left-menu-con .custom-navbar-icon-btn { height: 100%; border-radius: 200px; border: 1px solid rgba(220, 220, 220, 0.6); }
.custom-navbar-con .custom-navbar-left-menu-con .custom-navbar-icon-btn .icon { height: 90%; margin-top: 2.5%; }
.custom-navbar-con .custom-navbar-left-menu-con .custom-navbar-icon-btn .text { font-size: 27rpx; }
.custom-navbar-con .custom-navbar-left-menu-con .custom-navbar-icon-btn.back { border: none; }
.custom-navbar-con .custom-navbar-left-menu-con .custom-navbar-icon-btn.back~.custom-navbar-icon-btn.home { margin-left: 10rpx; }
.custom-navbar-con .custom-navbar-left-menu-con .custom-navbar-icon-btn.switch-shop { padding-left: 5px; padding-right: 25rpx; }

.custom-navbar-con.ios .custom-navbar-title.android { display: none; }
.custom-navbar-con.android .custom-navbar-title.ios { display: none; }
.custom-navbar-con .custom-navbar-title.ios { font-weight: bold; text-align: center; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); -webkit-transform: translate(-50%, -50%); }
.custom-navbar-con .custom-navbar-title.android { padding-left: 30rpx; }```

CustomNavBar.js


```javascript
module.exports = function(PageInstance) {
let App = getApp()

let _tplData = {
_CustomNavBar_: {
 navRightMenuRect: App.NavRightMenuRect,
 navRightMenuCenterY: App.NavRightMenuCenterY,
 statusBarHeight: App.StatusBarHeight,
 winWidth: App.WinWidth,
 winHeight: App.WinHeight,
 iOS: App.iOS,

navTitle: '', // 当前只合适短标题,如需长标题,建议隐藏自定义导航栏,自定义展示
 navHeight: App.CustomNavHeight,

needFixed: false,

showNavBar: !App.NavRightMenuRect ? false : true,
 showLeftMenu: true,
 showBackBtn: true,
 showHomeBtn: false
}
}

let _tplMethods = {
customNavBarBack() {
 wx.navigateBack()
},
customNavBarBackToHome() {
 let url = '/pages/index/index'
 wx.reLaunch({
 url: url
 })
}
}
let isIndexPage = !!(PageInstance.route == 'pages/index/index')
let pages = getCurrentPages()
if (pages.length == 1) {
_tplData._CustomNavBar_.showBackBtn = false
_tplData._CustomNavBar_.showHomeBtn = !isIndexPage
}

// 每个页面 可单独配置自定义导航栏
if (PageInstance.data.CustomNavBarConfig) {
Object.assign(_tplData._CustomNavBar_, PageInstance.data.CustomNavBarConfig)
}

// !!!! 最后执行
// 当无法获取到右上角按钮胶囊的布局位置时,强制设置自定义导航栏为隐藏状态
if (!App.NavRightMenuRect) {
_tplData._CustomNavBar_.showNavBar = false
}

Object.assign(PageInstance, _tplMethods)
PageInstance.setData(_tplData)
return this
}

app.js的配置


// 自定义导航栏
import CustomNavBar from './template/CustomNavBar/CustomNavBar';

App({
//自定义 模板式 组件
CustomNavBar,

// 系统信息
 WinWidth: 0,
 WinHeight: 0,
 StatusBarHeight: 0,
 PixelRatio: 1,
 SystemFullName: '',
 SystemVersion: '',
 SystemSDKVersion: '',

//自定义导航栏相关
 NavRightMenuRect: null,
 NavRightMenuCenterY: 0,
 CustomNavHeight: 0,

onLaunch: function (options) {
let self = this
let systemInfo = wx.getSystemInfoSync()
self.iOS = systemInfo.platform === 'ios'
self.isDebug = systemInfo.platform === 'devtools'
if (self.isDebug) {
 // 单纯为了在开发工具下调试 自定义导航栏
 // 开发工具下不存在App版本号的区分
 systemInfo.version = '7.0.0'
}
self.WinWidth = systemInfo.windowWidth
self.WinHeight = systemInfo.windowHeight
self.StatusBarHeight = systemInfo.statusBarHeight
// 部分小程序库版本没有返回状态栏高度
if (!self.StatusBarHeight) {
 self.StatusBarHeight = 20
}
self.PixelRatio = Math.max(systemInfo.pixelRatio, 2)
self.SystemFullName = systemInfo.system
self.SystemVersion = systemInfo.version
self.SystemSDKVersion = systemInfo.SDKVersion

// app.json全局配置的自定义导航栏的话,客户端需求版本为6.6.0
// 每个页面 单独配置的自定义导航栏的话,客户端需求版本为7.0.0
// wx.getMenuButtonBoundingClientRect方法,要求基础库版本为2.1.0
if (self.compareVersion(self.SystemVersion, '6.6.0') >= 0) {
 // 官方的6.6.0版本以上客户端,最低基础库版本为1.9.4
 // 6.6.0以上且[1.9.4 - 2.1.0]范围内的机型无法使用wx.getMenuButtonBoundingClientRect
 // 所以手动写死非全面屏手机的适配胶囊布局位置
 self.NavRightMenuRect = {
 top: 26,
 bottom: 58,
 right: self.WinWidth - 10,
 width: 87,
 height: 32
 }
 // 如果系统信息返回的状态栏高度大于20,认为是全面屏手机
 if (self.StatusBarHeight > 20) {
 self.NavRightMenuRect.top = 50
 self.NavRightMenuRect.bottom = 82
 }

// 2019年08月21日22:09:22
 // 微信小程序库出现bug,导致部分机型wx.getMenuButtonBoundingClientRect无返回值
 // 所以在这之前先默认写死一个NavRightMenuRect,防止全局的自定义导航栏已经隐藏了但是无法显示自定义导航栏
 // 详见https://developers.weixin.qq.com/community/develop/doc/00062238d78e880aedd88b72351c00
 if (wx.getMenuButtonBoundingClientRect) {
 let NavRightMenuRect = wx.getMenuButtonBoundingClientRect()
 self.NavRightMenuRect = {
  top: NavRightMenuRect.top,
  bottom: NavRightMenuRect.bottom,
  right: NavRightMenuRect.right,
  width: NavRightMenuRect.width,
  height: NavRightMenuRect.height
 }
 }

self.NavRightMenuCenterY = self.NavRightMenuRect.top + self.NavRightMenuRect.height / 2
 self.CustomNavHeight = self.NavRightMenuRect.bottom + (self.NavRightMenuRect.top - self.StatusBarHeight)
} else {
 self.NavRightMenuRect = null
 self.CustomNavHeight = 0
}
},

// 比较两个版本号
compareVersion (v1, v2) => {
  v1 = v1.split('.')
  v2 = v2.split('.')
  const len = Math.max(v1.length, v2.length)

while (v1.length < len) {
    v1.push('0')
  }
  while (v2.length < len) {
    v2.push('0')
  }

for (let i = 0; i < len; i++) {
    const num1 = parseInt(v1[i])
    const num2 = parseInt(v2[i])

if (num1 > num2) {
      return 1
    } else if (num1 < num2) {
      return -1
    }
  }
  return 0
}

}),

假如在index 页面引用

index.wxml


<!-- 自定义NavBar -->
<import src="../../template/CustomNavBar/CustomNavBar.wxml" />
<template is="CustomNavBar" data="{{ ..._CustomNavBar_ }}"></template>

index.js


onLoad: function(options) {
 new App.CustomNavBar(this)
}

来源:https://blog.csdn.net/qq_42911663/article/details/103065517

标签:微信小程序,导航栏
0
投稿

猜你喜欢

  • 轻松解决:mysql数据库连接过多的错误

    2010-09-30 14:28:00
  • Python查找数组中数值和下标相等的元素示例【二分查找】

    2023-11-04 12:55:45
  • MySQL脏读幻读不可重复读及事务的隔离级别和MVCC、LBCC实现

    2024-01-19 00:23:03
  • SQL Server的FileStream和FileTable深入剖析

    2023-07-17 01:17:24
  • 新发现一个骗链接的方法(js读取cookies)

    2024-10-06 12:07:19
  • Python实现制作透明背景的电子印章

    2022-01-20 08:11:24
  • CSS入门了解CSS的伪类

    2007-10-24 19:36:00
  • 由浅入深学习TensorFlow MNIST 数据集

    2021-06-04 23:57:52
  • golang 实现json类型不确定时的转换

    2024-05-05 09:26:07
  • js计算精度问题小结

    2024-04-10 13:55:24
  • Python简单网络编程示例【客户端与服务端】

    2023-12-07 10:26:55
  • PHP session有效期session.gc_maxlifetime

    2023-11-14 17:01:45
  • 用python3读取python2的pickle数据方式

    2023-06-05 09:45:48
  • python smtplib发送多个email联系人的实现

    2023-07-24 18:39:43
  • 统一的品牌设计

    2008-08-07 12:53:00
  • 不受欢迎的“欢迎页”

    2008-04-20 16:41:00
  • Python爬虫实战之爬取京东商品数据并实实现数据可视化

    2023-11-02 18:42:38
  • Bootstrap媒体对象的实现

    2024-04-22 22:42:23
  • python+matplotlib绘制简单的海豚(顶点和节点的操作)

    2023-11-14 11:10:27
  • python函数中return后的语句一定不会执行吗?

    2022-03-25 04:06:44
  • asp之家 网络编程 m.aspxhome.com