背景

在做小程序时,关于默认导航栏,我们遇到了以下的问题:

  • Android、IOS 手机对于页面 title 的展示不一致,安卓 title 的显示不居中
  • 页面的 title 只支持纯文本级别的样式控制,不能够做更丰富的 title 效果
  • 左上角的事件无法监听、定制
  • 路由导航单一,只能够返回上一页,深层级页面的返回不够友好

探索

小程序自定义导航栏已开放许久>>了解一下,相信不少小伙伴已使用过这个功能,同时不少小伙伴也会发现一些坑:

  • 机型多如牛毛:自定义导航栏高度在不同机型始终无法达到视觉上的统一
  • 导航栏中内容怎么都不垂直居中对齐,更别说适配所有手机
  • 调皮的胶囊按钮:导航栏元素(文字,图标等)怎么也对不齐那该死的胶囊按钮
  • 各种尺寸的全面屏,奇怪的刘海屏,简直要抓狂

一探究竟

为了搞明白原理,我先去翻了官方文档,>>飞机,点过去是不是很惊喜,很意外,通篇大文尽然只有最下方的一张图片与这个问题有关,并且啥也看不清,汗汗汗…

我特意找了一张图片来

分析上图,我得到如下信息:

  • Android 跟 iOS 有差异,表现在顶部到胶囊按钮之间的距离差了 6pt
  • 胶囊按钮高度为 32pt, iOS 和 Android 一致

动手分析

我们写一个状态栏,通过 wx.getSystemInfoSync().statusBarHeight 设置高度

Android:

iOS:

可以看出,iOS 胶囊按钮与状态栏之间距离为:4px, Android 为 8px,是不是所有手机都是这种情况呢?
答案是:苹果手机确实都是 4px,安卓大部分都是 7 和 8 也会有其他的情况(可以自己打印 getSystemInfo 验证)如何快速便捷算出这个高度,请接着往下看

如何计算

导航栏分为状态栏和标题栏,只要能算出每台手机的导航栏高度问题就迎刃而解

  • 导航栏高度 = 胶囊按钮高度 + 状态栏到胶囊按钮间距 * 2 + 状态栏高度

注:由于胶囊按钮是原生组件,为表现一致,其单位在各种手机中都为 px,所以我们自定义导航栏的单位都必需是 px(切记不能用 rpx),才能完美适配。

解决问题

现在我们明白了原理,可以利用胶囊按钮的位置信息和 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 请移步下方代码仓库,代码中还会有输入框文字跳动解决办法,安卓手机输入框文字飞出解决办法,左侧按钮边框太粗解决办法等等

胶囊信息报错和获取不到

问题就在于 getMenuButtonBoundingClientRect 这个方法,在某些机子和环境下会报错或者获取不到,对于此种情况完美可以模拟一个胶囊位置出来

try {rect = Taro.getMenuButtonBoundingClientRect ? Taro.getMenuButtonBoundingClientRect() : null;if (rect === null) {throw 'getMenuButtonBoundingClientRect error';}//取值为0的情况if (!rect.width) {throw 'getMenuButtonBoundingClientRect error';}
} catch (error) {let gap = ''; //胶囊按钮上下间距 使导航内容居中let width = 96; //胶囊的宽度,android大部分96,ios为88if (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);
}

以上代码主要是借鉴了拼多多的默认值写法,android 机子中 gap 值大部分为 8,ios 都为 4,开发工具中 ios 为 5.5,android 为 7.5,这样处理之后自己模拟一个胶囊按钮的位置,这样在获取不到胶囊信息的情况下,可保证绝大多数机子完美显示导航头

吐槽

这么重要的问题,官方尽然没有提供解决方案…竟然提供了一张看不清的图片???

网上有很多 ios 设置 44,android 设置 48,还有根据不同的手机型号设置不同高度,通过长时间的开发和尝试,本人发现以上方案并不完美,并且 bug 很多

代码库

  • Taro 组件gitHub 地址详细用法请参考 README
  • 原生组件 npm 构建版本gitHub 地址详细用法请参考 README
  • 原生组件简易版gitHub 地址详细用法请参考 README
  • 由于本人精力有限,目前只计划发布维护好这 2 种组件,其他组件请自行修改代码,有问题请联系

备注

  • 上方 2 种组件在最下方 30 多款手机测试情况表现良好
  • iPhone 手机打电话和开热点导致导航栏样式错乱,问题已经解决啦,请去 demo 里测试,这里特别感谢 moments 网友提出的问题
  • 本文章并无任何商业性质,如有侵权请联系本人修改或删除
  • 文章少量部分内容是本人查询搜集而来
  • 如有问题可以下方留言讨论,微信 zhijunxh

比较

斗鱼:

虎牙:

微博:

酷狗:

知乎:

知乎是这里边做的最好的,但是我个人认为有几个可以优化的小问题

  • 打电话或者开启热点导致样式错落,这也是大部门小程序的问题
  • 导航栏下边距太小,看起来不舒服
  • 搜索框距离 2 侧按钮组距离不对等
  • 自定义返回和 home 按钮中的竖线颜色重了,并且感觉太粗

如果您看到了此篇文章,请赶快修改自己的代码,并运用在实践中吧

扫码体验我的小程序:

创作不易,如果对你有帮助,请移步 Taro 组件gitHub原生组件gitHub给个星星 star✨✨ 谢谢

测试信息

手机型号 胶囊位置信息 statusBarHeight 测试情况
iPhoneX 80 32 281 369 48 88 44 通过
iPhone8 plus 56 32 320 408 24 88 20 通过
iphone7 56 32 281 368 24 87 20 通过
iPhone6 plus 56 32 320 408 24 88 20 通过
iPhone6 56 32 281 368 24 87 20 通过
HUAWEI SLA-AL00 64 32 254 350 32 96 24 通过
HUAWEI VTR-AL00 64 32 254 350 32 96 24 通过
HUAWEI EVA-AL00 64 32 254 350 32 96 24 通过
HUAWEI EML-AL00 68 32 254 350 36 96 29 通过
HUAWEI VOG-AL00 65 32 254 350 33 96 25 通过
HUAWEI ATU-TL10 64 32 254 350 32 96 24 通过
HUAWEI SMARTISAN OS105 64 32 326 422 32 96 24 通过
XIAOMI MI6 59 28 265 352 31 87 23 通过
XIAOMI MI4LTE 60 32 254 350 28 96 20 通过
XIAOMI MIX3 74 32 287 383 42 96 35 通过
REDMI NOTE3 64 32 254 350 32 96 24 通过
REDMI NOTE4 64 32 254 350 32 96 24 通过
REDMI NOTE3 55 28 255 351 27 96 20 通过
REDMI 5plus 67 32 287 383 35 96 28 通过
MEIZU M571C 65 32 254 350 33 96 25 通过
MEIZU M6 NOTE 62 32 254 350 30 96 22 通过
MEIZU MX4 PRO 62 32 278 374 30 96 22 通过
OPPO A33 65 32 254 350 33 96 26 通过
OPPO R11 58 32 254 350 26 96 18 通过
VIVO Y55 64 32 254 350 32 96 24 通过
HONOR BLN-AL20 64 32 254 350 32 96 24 通过
HONOR NEM-AL10 59 28 265 352 31 87 24 通过
HONOR BND-AL10 64 32 254 350 32 96 24 通过
HONOR duk-al20 64 32 254 350 32 96 24 通过
SAMSUNG SM-G9550 64 32 305 401 32 96 24 通过
360 1801-A01 64 32 254 350 32 96 24 通过

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

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

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

  2. taro 请务必在小程序页面中完善页面基础信息_小程序自定义导航栏(完美适配所有手机)...

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

  3. 小程序自定义导航栏(完美适配所有手机)解决上下不居中 左右不对齐 高度不协调问题...

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

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

    微信小程序头部导航栏自定义 参考网址微信开放文档 navigationStyle导航栏样式:仅支持以下值:default默认样式,custom 自定义导航栏,只保留右上角胶囊按钮 配置示例 {&quo ...

  5. 微信小程序顶部导航栏自定义,根据不同手机自适应距离状态栏高度,防止标题栏高度歪歪扭扭

    微信小程序顶部导航栏自定义,根据不同手机自适应距离状态栏高度 一.微信小程序顶部导航栏自定义 "navigationStyle": "custom"  app. ...

  6. 微信小程序navigationBarTitleText导航栏标题设置

    微信小程序navigationBarTitleText导航栏标题设置 全局设置 app.json "window": { "navigationBarTextStyle& ...

  7. 微信小程序顶部导航栏样式设置(自定义)

    效果: 一.要用自定义的导航栏需要在app.json中配置(必须) 取消自带的导航栏:"navigationStyle": "custom" 目前微信小程序不支 ...

  8. 微信小程序tabBar导航栏页和其他页执行onLoad与onShow时机;tabBar页获取不到参数问题;navigateTo跳转无效问题;onShow执行两次问题;

    1.注意点: 只有五种情况会触发导航栏tabBar页的onLoad函数,分别是: –1.1:首次进入到导航栏tabBar页面: –1.2:从微信分享进入的导航栏tabBar页面: –1.3:识别二维码 ...

  9. 微信小程序之导航栏样式修改、自定义导航栏及封装

    在微信小程序中我们会经常看到不同字样的顶部标题,这样的样式有的是一样的,而有的却又是不同的导航栏,这是怎么回事呢,在这里我们就探讨一下.(微信小程序json文件不能有注释,复制过去的时候有注释记得自行 ...

最新文章

  1. linux用户层驱动--VFIO(五)
  2. Python学习之路—2018/7/14
  3. centos7.5安装influxdb-1.7.8
  4. Redis Sentinel 配置文件
  5. 向DWR传递map/返回map/list/set等(返回对象的处理)
  6. web图像_Web图像优化的基本介绍
  7. 华为连发4款手机:配置售价感人
  8. java 输出字符集合里的字_Java基础 -- 字符串(格式化输出、正则表达式)(示例代码)...
  9. 报表填报时,如何实现多个单元格绑定一个字段?
  10. python可视化入门 plotly
  11. VB6之从1970年1月1日起的秒数 的与C语言类似的时间函数
  12. mysql innodb备份恢复和主从复制 xtrabackup工具的使用
  13. springboot项目打包成jar包
  14. CentOS7.5 怎么修改默认SSH端口号
  15. python多线程爬取qq好友空间的留言
  16. 互联网进化论在中国科技论文在线正式发表
  17. 读《最重要的事只有一件》有感
  18. Mingle 2.0 发布了
  19. 计算机系统基础实验 - 同符号浮点数加法运算/无符号定点数乘法运算的机器级表示
  20. 阿里云漏洞敏捷管理自动化报告

热门文章

  1. 简单工厂模式——2016手机也疯狂
  2. 直播场控话术总结?网红直播间控场欢迎语大全第一期
  3. 如何打开dwg文件是比较的方便的
  4. 亚稳态的几种解决方法
  5. Java开发经典实战!java正则表达式匹配字符串替换
  6. MySQL最全整理!java垃圾回收器的作用不包括
  7. 计算机需要学大学物理吗,计算机系要学大学物理吗?
  8. java a3 套打印_Java输出打印工具类封装的实例
  9. 微信小程序中嵌套html_微信小程序中使用 web-view 内嵌 H5 时,登录问题的处理方法...
  10. PyTorch 2.0 实操:为 HuggingFace 和 TIMM 模型提速!