小程序自定义导航栏 完美解决上下不居中 左右不对称

2019-08-16

背景

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

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

探索

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

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

一探究竟

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

我特意找了一张图片来 小程序导航栏分析上图,我得到如下信息:

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

接着分析

  • 胶囊按钮到状态栏下边缘这块距离,好像是固定的?
  • 安卓这个图,好像有点奇怪?导航栏分为 状态栏+标题栏?
  • 如果前两个条件成立,那我们的问题是不是就解决了80%?

第一个问题

很简单,我们写一个状态栏,通过wx.getSystemInfoSync().statusBarHeight设置高度, 为了好测量,我们设置状态栏背景色为深色

Android: AndroidiOS: iOS

可以看出,iOS胶囊按钮与状态栏之间距离为:6px, Android为8px,并且经过测量,iOS各机型,Android各机型结果一致(有兴趣的可以自行测量)

第二个问题

导航栏分为 状态栏+标题栏?

通过对第一个问题的论证,很明显能看出来确实是这样的。并且通过第一个问题的测量结果以及官方提供的数据,我们可以对标题栏高度进行计算:

  • 导航栏高度 = 胶囊按钮高度 + 状态栏到胶囊按钮间距 * 2
  • Android导航栏高度 = 32px + 8px * 2 = 48px
  • iOS导航栏高度 = 32px + 6px * 2 = 44px

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

解决问题

利用胶囊按钮的位置信息和statusBarHeight高度动态计算navbar的高度, 贴一个实现此功能重要的方法过程

let rect = Taro.getMenuButtonBoundingClientRect ? Taro.getMenuButtonBoundingClientRect() : null;
    Taro.getMenuButtonBoundingClientRect();
    let navBarHeight = (function() {
      let gap = ''; //胶囊按钮上下间距 使导航内容居中
      if (systemInfo.platform === 'android') {
        gap = 8;
      } else if (systemInfo.platform === 'devtools') {
        if (ios) {
          gap = 5.5; //开发工具中ios手机
        } else {
          gap = 7.5; //开发工具中android和其他手机
        }
      } else {
        gap = 4;
      }
      return systemInfo.statusBarHeight + 2 * gap + rect.height;
    })();

gap信息就是用来确定不同的手机需要添加的间隙距离,具体实现和demo请移步下方代码仓库

吐槽

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

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

代码库

测试信息

手机型号胶囊位置信息statusBarHeight测试情况
iPhone8 plus56 32 320 408 24 8824通过
iphone756 32 281 368 24 8720通过
iPhone6 plus56 32 320 408 24 8820通过
iPhone656 32 281 368 24 8720通过
HUAWEI SLA-AL0064 32 254 350 32 9624通过
HUAWEI VTR-AL0064 32 254 350 32 9624通过
HUAWEI EVA-AL0064 32 254 350 32 9624通过
HUAWEI EML-AL0068 32 254 350 36 9629通过
HUAWEI VOG-AL0065 32 254 350 33 9625通过
HUAWEI SMARTISAN OS10564 32 326 422 32 9624通过
XIAOMI MI659 28 265 352 31 87未记录通过
XIAOMI MI4LTE60 32 254 350 28 9620通过
XIAOMI MIX374 32 287 383 42 9620通过
REDMI NOTE364 32 254 350 32 9620通过
REDMI NOTE464 32 254 350 32 9624通过
REDMI NOTE355 28 255 351 27 9620通过
MEIZU M571C65 32 254 350 33 9625通过
MEIZU M6 NOTE62 32 254 350 30 9622通过
MEIZU MX4 PRO62 32 278 374 30 9622通过
OPPO A3365 32 254 350 33 9626通过
VIVO Y5564 32 254 350 32 9624通过
HONOR BLN-AL2064 32 254 350 32 9624通过
HONOR NEM-AL1059 28 265 352 31 8724通过

  • 本文章并无任何商业性质,如有侵权请联系本人修改或删除
  • 文章部分内容是本人查询搜集而来,代码都是本人所写
  • 上述测试信息是taro组件测试信息,近期增加小程序原生组件测试信息
  • 如有问题可以下方留言讨论,或者仓库提pr

比较

斗鱼: 斗鱼

微博: 微博

酷狗: 酷狗

知乎: 知乎

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

  • 导航栏下边距太小,看起来不舒服
  • 搜索框距离2侧按钮组距离不对等
  • 自定义返回和home按钮中的竖线颜色重了,并且感觉太粗
  • 如果您看到了此篇文章,请赶快修改自己的代码,并可运用在实践中

扫码体验我的小程序: 垃圾分类

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

原文链接:segmentfault.com

上一篇:vue cli3 + typescript 简易贴吧
下一篇:美化文件上传按钮自定义input file样式
相关教程
关注微信

扫码加入 JavaScript 社区

相关文章

首次访问,需要验证
微信扫码,关注即可
(仅需验证一次)

欢迎加入 JavaScript 社区

号内回复关键字:

回到顶部