navigationBar是什么?

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

小程序布局

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

wx.getSystemInfo()

image

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

image

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

为什么要自定义navigationBar?

原生导航栏的限制

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

产品需求

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

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

携程navigationBar

斗鱼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

image

  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的布局方法多种多样,上面只是列出了笔者的一种写法。
  • 学习小程序,自定义导航栏是很重要的技能,其间的逻辑并不复杂,还是和学习前端一样,需要非常细心耐心,才能做好细节工作。

转载-链接:https://www.jianshu.com/p/9822d9ee168e
来源:简书

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

  1. 微信小程序自定义navigationbar与下拉刷新思考

    第一次开发小程序,产品提出要求导航栏字体样式,然后系统的未提供修改的接口. 那么只能自定义导航栏才行呀. 迅速的自定义了一个导航栏 app.json中添加 "navigationStyle& ...

  2. 微信小程序自定义navigationBar、自定义标题栏

    最近在做小程序项目,需要用到自定义navigationBar,之前用过colorUI等组件库的navigationBar组件,但是现在想自己写一个,所以有了今天的小记 在做navigationBar之 ...

  3. 微信小程序自定义navigationBar顶部导航栏,兼容安卓ios

    1.设置导航栏自定义"navigationStyle":"custom" "pages": [ //pages数组中第一项表示应用启动页,参 ...

  4. 微信小程序自定义navigation-bar导航栏(自适应安卓苹果)

    最近在写商城,中途遇到了需要自定义修改导航栏的操作,大概是如下图接过样子的,于是想手写一份,但我发现右上角的分享按钮在不同设备离顶部的距离是不一样的,于是找了下官方划水员写的文档(点这里查看),(⊙o ...

  5. 微信小程序-自定义导航栏及返回上一级页面的实现

    一.参考文章 1.微信小程序自定义navigationBar 2.微信小程序返回上一级页面的实现代码 3.小程序开发--常用布局 二.需求 在导航栏中需要显示信息的"未读数量",所 ...

  6. 原声微信小程序自定义顶部导航栏 . 自定义navigationBar。 (单页面设置)

    本文实例为大家分享了微信小程序自定义导航栏的具体代码,供大家参考,具体内容如下 实现自定义大致需要以下?步骤: 1.在页面.JSON文件进行相关配置,以便去掉原生 "navigationSt ...

  7. 微信小程序自定义授权弹框

    微信小程序自定义授权弹框 最近微信获取用户信息的接口有调整,就是这货:wx.getUserInfo(OBJECT),文档描述如下: 此接口有调整,使用该接口将不再出现授权弹窗,请使用 <butt ...

  8. 微信小程序自定义组件方案

    前言:小程序已于11月初开放了小程序组件功能,但事件方面还不是很完善,有的组件暂时可能还是要用其他方式来实现,这里简单记录下开发小程序自定义组件的要点. 在小程序官方开发组件开发功能之前,自定义组件的 ...

  9. 微信小程序自定义组件,提示组件

    微信小程序自定义组件,这里列举了一个常用的提示自定义组件,调用自定义组件中的方法和字段.仅供参考和学习. 编写组件: 在根目录下添加"components"目录,然后像添加Page ...

最新文章

  1. 让机器“自愈化”引领新科技变革
  2. Vue.js 从 Vue 1.x 迁移
  3. WPF Tile=” 变量 UI 双向绑定”x:Class=Problem/
  4. 双柱状图柱子数量比较多_一条代码完成堆叠柱状图-冲击图的操作-终结版
  5. asp.net core 3.0 gRPC框架小试
  6. java 双因素认证(2FA)TOTP demo
  7. [DIV/CSS] 【译】60个有用CSS代码片段
  8. php后门 佛像,35张活的再久,也未必见过的照片,图2是佛像通过CT扫描后内部照...
  9. (器) 构建自由通行的IOS开发者地图
  10. Linux内创建新用户,linux下手工创建新用户
  11. CentOS 7搭建tengine+php+mariadb环境并安装discuz论坛
  12. c++ 11之 lambda表达式的使用
  13. Python做人工智能?让电脑自己学会玩游戏,实战带你入门机器学习
  14. 商品房价不会下跌的六大理由
  15. cpci检索太慢_了解CPCI检索,对自己的好处
  16. 物联网-移远M26模块初识及资料分享
  17. RHEL6 安装gstreamer 实现 rhythmbox 听mp3歌曲
  18. 自建exchange邮箱有什么成熟的超大附件解决方案?
  19. 【工作记录】VRLe工作总结
  20. 我的三偶之:迈克尔.杰克逊(Micheal Jackson)

热门文章

  1. 《Head First Java》读书笔记(叁)
  2. 如何将Excel文件中数据导入数据库
  3. 全网最全、最新Maven构建工具核心知识,这篇文章包你这辈子也忘不掉Maven!!
  4. 如何在Ubuntu16.04下配置移远RM500工业模组(5G工业模组)
  5. 第三届第五空间网络安全大赛WP(部分)
  6. scu4438(KMP)
  7. 博途PLC单神经元自适应PID控制
  8. ebooks/算法导论官方配套课件下载(英文版)(Introduction to Algorithms,v3)中英部分内容对比/电子版教材下载/阅读/高中数学下载(zlib/微信读书)
  9. 见过最好的神经网络CNN解释
  10. java filebody出错_java-FileNotFoundException打开失败:Samsung设备上...