这里使用三段论是什么为什么怎么做来阐述自定义navigationBar,如果只关心怎么做可直接跳至怎么做段落。

navigationBar是什么?

  • 微信小程序一般来说有两个bar,一个导航栏,一个tabbar(小程序下方一排切换按钮),实现下方自定义tabbar的方法一般来说较为简单,现在着重叙述上方自定义导航栏的实现。

小程序布局

  • 谈到导航栏与自定义导航栏,就需要解释一下微信小程序的布局了。在小程序开发中使用wx.getSystemInfo() 方法可以获取到系统信息。

  • 部分获取到的信息如上图(截取自微信小程序开发者文档),对我们理解布局有用的信息是以上跟宽度高度相关的属性,如当前设备的屏幕高宽,可用高宽,以及saveArea。

  • 上图展示我们从systemInfo获取到的数据的实际表现,以苹果X的刘海屏为例(所有安卓刘海屏原理类似):最外层的红色框即屏幕大小,蓝色框即安全区域字面意思也就是开发者所能操纵的页面区域,上面的黄色框即手机的状态栏,绿色区域即我们要自定义的navigationBar
  • 可见,导航栏紧贴safeArea的上部,如果使用原生导航栏,导航栏下方即是真正意义的可操控范围。
  • 实际上我们自定义的导航栏也是在这个safeArea内与胶囊对齐最为和谐。很关键的原因就是微信将右上角的胶囊按钮作为了内置组件,只有黑白两种颜色,即我们无法改变它的大小位置透明度等等,所以为了配合胶囊按钮,一般自定义的导航栏位置也与上图位置一致。

为什么要自定义navigationBar?

原生导航栏的限制

  • 除了胶囊按钮以外,原生导航栏只会出现返回按钮和当用户打开的小程序最底层页面是非首页时,默认展示的“返回首页”按钮 。
  • 原生导航栏的标题文字的颜色只有黑白。
  • 布局无法改变,不能做定制。

产品需求

  • 如果说原生导航栏的限制还不足以让你加入自定义导航栏,那么产品需求绝对是更大的推动力。

  • 自定义导航栏除了不能自定义胶囊按钮以外,其他的范围都是程序员的掌控范围,所以使用自定义导航栏无疑可以满足产品的各种需求。

  • 如果你的产品有上图的需求,显然你不能say no,你只能满足需求,加上自定义navigationBar。

自定义navigationBar怎么做?

去掉原生导航栏。

  1. 将需要自定义navigationBar页面的page.json的navigationBarTitleText去掉。
  2. 加上"navigationStyle":"custom",这样原生的导航栏就已经消失,甚至后退键也不会出现需要自定义。
  3. 另外,早在2016年微信已经开始适配沉浸式状态栏,目前几乎所有的机型里微信都是沉浸式状态栏,也就是说去掉原生导航栏的同时,整个屏幕已经成为可编程区域

计算navigationBarHeight。

  • 原生的胶囊按钮当然存在,那么下一步就需要你去定位出自定义的导航栏高度以及位置。
  • 对于不同的机型,对于不同的系统,状态栏以及胶囊按钮的位置都不确定,所以需要用到一定的计算,从而面对任何机型都可以从容判定。
  1. 使用"wx.getSystemInfo()“获取到"statusBarHeight”,这样就确定了导航栏最基本的距离屏幕上方的据里。
  2. 使用"wx.getMenuButtonBoundingClientRect()"获取到小程序的胶囊信息(注意这个api存在各种问题,在不同端表现不一致,后面会叙述这个api调用失败的处理情况),如下图,以下坐标信息以屏幕左上角为原点。

  1. 以下图为例,上面的红色框是statusBar,高度已知;下面的红色框是正文内容,夹在中间的就是求解之一navigationBarHeight;而黄色的是原生胶囊按钮也是在垂直居中位置,高度为胶囊按钮基于左上角的坐标信息已知,不难得出,navigationBarHeight = 蓝色框高度 × 2 + 胶囊按钮.height。(蓝色框高度 = 胶囊按钮.top - statusBarHeight)

  1. 最后的计算公式为:navigationBarHeight = (胶囊按钮.top - statusBarHeight) × 2 + 胶囊按钮.height。navigationBar 距屏幕上方的距离即为navigationBarHeight。

  2. 这种计算方法在各种机型以及安卓ios都适用。

  3. 针对"wx.getMenuButtonBoundingClientRect()"获取错误或者获取数据为0的极少数情况,只能够去模拟,对于android,一般navigationBarHeight为48px,而对于ios一般为40px,所有机型的胶囊按钮高度是32px笔者也是通过网上很多的文章和自测得出的,这种误差一般可以忽略。当然最理想的就是微信可以hold住所有机型,呵呵。最后提醒一下仅以真机为准,开发者工具的bug就更多不说了。

代码实现

  • 获取本机信息,笔者一般写在App的onLaunch中。

App.js

// App.js
...
onLaunch(){const { statusBarHeight, platform } = wx.getSystemInfoSync()const { top, height } = wx.getMenuButtonBoundingClientRect()// 状态栏高度wx.setStorageSync('statusBarHeight', statusBarHeight)// 胶囊按钮高度 一般是32 如果获取不到就使用32wx.setStorageSync('menuButtonHeight', height ? height : 32)// 判断胶囊按钮信息是否成功获取if (top && top !== 0 && height && height !== 0) {const navigationBarHeight = (top - statusBarHeight) * 2 + height// 导航栏高度wx.setStorageSync('navigationBarHeight', navigationBarHeight)} else {wx.setStorageSync('navigationBarHeight',platform === 'android' ? 48 : 40)}
}
...
  • 笔者将这几个高度信息储存在stroage中,之后创建navigationBar自定义组件,在组件中将会运用到这些数据。

navigationBar.js

// navigationBar.js
...
data: {// 状态栏高度statusBarHeight: wx.getStorageSync('statusBarHeight') + 'px',// 导航栏高度navigationBarHeight: wx.getStorageSync('navigationBarHeight') + 'px',// 胶囊按钮高度menuButtonHeight: wx.getStorageSync('menuButtonHeight') + 'px',// 导航栏和状态栏高度navigationBarAndStatusBarHeight:wx.getStorageSync('statusBarHeight') +wx.getStorageSync('navigationBarHeight') +'px'
}
...
  • navigationBar.wxml中的布局就不多赘述,一般来说,导航栏使用fixed定位,里面再通过行内垂直居中的方式定位自定义的返回按钮,还有居中导航标题,以及字数过多显示省略号等。

navigationBar.wxml

<!--navigationBar.wxml-->
<view class="navigation-container" style="{{'height: ' + navigationBarAndStatusBarHeight}}"><!--空白来占位状态栏--><view style="{{'height: ' + statusBarHeight}}"></view><!--自定义导航栏--><view class="navigation-bar" style="{{'height:' + navigationBarHeight}}"><view class="navigation-buttons" style="{{'height:' + menuButtonHeight}}"><image class="nav-img" src='/images/back.svg'/>...其余自定义button</view> <view class="navigation-title" style="{{'line-height:' + navigationBarHeight}}">{{title}}</view></view>
</view>
<!--空白占位fixed空出的位置-->
<view style="{{'height: ' + navigationBarAndStatusBarHeight}}; background: #ffffff"></view>

navigationBar.wxss

/* navigationBar.wxss */
.navigation-container {position: fixed;width: 100%;z-index: 99;top: 0;left: 0;background-color: #ffffff;
}
.navigation-bar {position: relative;display: flex;flex-direction: row;align-items: center;
}
.navigation-buttons {display: flex;align-items: center;margin-left: 10px;border: 1px solid rgba(0, 0, 0, 0.05);box-sizing: border-box;border-radius: 15px;background-color: transparent;
}
.nav-img{height: 16px;width: 16px;
}
.navigation-title {position: absolute;left: 104px;right: 104px;text-align: center;font-size: 16px;font-weight: bold;color: #000000;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;
}

总结

  • 自定义导航栏核心在于导航栏的高度定位,这样才能准确定位自定义的返回按钮以及其他按钮的位置,与原生胶囊保持一致。至于wxml的布局方法多种多样,上面只是列出了笔者的一种写法。
  • 学习小程序,自定义导航栏是很重要的技能,其间的逻辑并不复杂,还是和学习前端一样,需要非常细心耐心,才能做好细节工作。

微信小程序自定义导航栏navigationBar相关推荐

  1. 微信小程序自定义导航栏(带汉堡包菜单)

    微信小程序自定义导航栏(带汉堡包菜单) 1.在app.json中 window配置navigationStyle (如果单独页面使用,可在页面的json文件配置) 2.计算相关值 整个导航栏的高度: ...

  2. 微信小程序自定义导航栏 navigation bar 返回键 首页

    微信小程序自定义导航栏(wx_custom_navigation_bar) 自定义返回键.首页键,动态设置标题,响应式组件 版本号:2.0.0 作者:chen-yt github: https://g ...

  3. 微信小程序自定义导航栏如何实现(简洁版)~内附代码

    先来张效果图 实现起来也是十分容易的,几行代码. Page({data: {},onLoad() {// 获取设备的信息let menuButtonObject = wx.getMenuButtonB ...

  4. 微信小程序-自定义导航栏

    微信小程序-自定义导航栏 第一步 添加属性 "navigationStyle": "custom" 第二步 自定义导航栏 第二步 自定义组件 第四步 使用组件 ...

  5. 微信小程序自定义导航栏组件

    效果图 首先要先在 json文件里加上 "navigationStyle":"custom", 这句,去掉原生的自定义导航栏 一.子组件-wxml <vi ...

  6. 微信小程序自定义导航栏组件,完美适配所有手机,可实现各种功能和情况

    背景 在做小程序时,关于默认导航栏,我们遇到了以下的问题: Android.IOS手机对于页面title的展示不一致,安卓title的显示不居中 页面的title只支持纯文本级别的样式控制,不能够做更 ...

  7. 微信小程序自定义导航栏机型适配--底部Tabbar--view高度--底部按钮适配

    自定义微信小程序头部导航栏 自定义微信小程序头部导航栏,有几种方式 方式一 {"navigationStyle": "custom" // 将navigatio ...

  8. 微信小程序自定义导航栏返回和标题

    1.新建组件 index.json {"component": true } navbar.wxss //navbar.wxss .navbar{width: 100%;//设置导 ...

  9. 微信小程序自定义导航栏组件(完美适配所有手机),可自定义实现任何你想要的功能

    背景 在做小程序时,关于默认导航栏,我们遇到了以下的问题: Android.IOS 手机对于页面 title 的展示不一致,安卓 title 的显示不居中 页面的 title 只支持纯文本级别的样式控 ...

最新文章

  1. 经典的导航二级式导航菜单增强版
  2. 使用Combox控件的一个问题
  3. tar - tar 档案文件管理程序的 GNU 版本。
  4. Linux 查看并删除.svn目录
  5. python学习使用
  6. mysql全量备份、增量备份实现方法
  7. 【Qt学习笔记】7.对话框Dialog
  8. Vue 项目上线优化
  9. DAVINCI开发原理之三----达芬奇编解码引擎Codec Engine(CE)
  10. HDOJ水题集合4:杂题
  11. Spring Boot的每个模块包详解
  12. VS项目属性的一些配置项的总结(important)
  13. 使用SCVMM2008 R2管理Hyper-V之3-使用模板部署虚拟机
  14. 集体智慧编程_6文档过滤
  15. 怎么做简单版ps碎片飞溅效果
  16. 京东云主机使用-搭建简单网页(macOS)
  17. linux下迅雷的替代
  18. QT在QML下实现多国语言翻译
  19. Linux alsa-lib c语言 播放wav音频
  20. 关闭安卓手机的按键背景灯

热门文章

  1. 45个必备的JavaScript Web开发工具
  2. outlook正在加载配置无法打开
  3. 2022年全球市场生物可吸收胶原蛋白植入物总体规模、主要生产商、主要地区、产品和应用细分研究报告
  4. 2023-2028年中国胶原蛋白行业深度调研与投资趋势分析报告
  5. 工作的思考十三:自我反省+控制情绪+高度和角度
  6. Allegro导入PADS文件
  7. 腾讯云直播集成app时报错 Duplicate class com.xxx:
  8. web前端学习(八)——HTML5中表格、边框的相关标签设置
  9. 匹配滤波处理不同距离维回波信号
  10. 2023年华中杯数学建模A题新型镇静药物临床实验疗效分析与预测解题全过程文档及程序