小程序实现自定义导航栏适配完美版


Posted in Javascript onApril 02, 2019

1、发现问题

小程序页面自定义导航栏功能已经开放有些日子了(还不知道这个功能的可以先>>了解一下),这极大的提升了小程序开发的自由度,相信不少小伙伴已经使用过这个功能,同时也相信不少小伙伴在此功能开发过程中踩过同样的一些坑:

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

同样的,这些问题也是小灰经历过的。但是小灰相信,办法总比问题多,于是开始了自己的探究:

2、一探究竟

为了搞明白到底该怎么去适配,老规矩,我先翻了一波官方文档,还别说,官方还真有这么一段介绍了相关细节,>>详情点击:

小程序实现自定义导航栏适配完美版

从图中分析,我们可以得到如下信息:

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

这。。。,好像并没有什么L用啊??这仅仅是普通屏幕为参照的,ipx, 安卓全面屏完全没介绍。
沉着冷静,我们接着分析:

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

那么我们来论证一下:

第一个问题:胶囊按钮到状态栏下边缘的距离是不是固定的?

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

为了好测量,我们设置状态栏背景色为深色

js代码:

var sysinfo = wx.getSystemInfoSync();
this.setData({ 
 statusBarHeight:sysinfo.statusBarHeight 
})

wxml代码:

<view class="status-bar" style="height:{{statusBarHeight}}px"></view>

wxss代码:

.status-bar{
 background: rgb(141, 71, 71);
 }

效果图(iPhone6):

小程序实现自定义导航栏适配完美版

效果图(iPhoneX):

小程序实现自定义导航栏适配完美版

效果图(安卓):

小程序实现自定义导航栏适配完美版

是不是有点眉目了?是的,从截图可以看出,iOS是一致的,但是Android好像有所差别。

那究竟距离是多少?我们用神器(微信截图)来量一量:

Android:

小程序实现自定义导航栏适配完美版

iOS:

小程序实现自定义导航栏适配完美版

可以看出,iOS胶囊按钮与状态栏之间距离为:6px, Android为8px,并且经过测量,iOS各机型,Android各机型结果一致(由于篇幅原因,就不一一展示截图了,有兴趣的可以自行测量)

第二个问题:导航栏分为 状态栏+标题栏?

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

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

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

3、解决问题

通过上述分析,相信小伙伴们都能有一个解决问题的思路了,在上代码之前,小灰再给大家画一下重点:

  • 写自定义导航组件的时候,需要将组件结构一分为二:状态栏 + 标题栏
  • 状态栏高度可通过wx.getSystemInfoSync().statusBarHeight获取
  • 标题栏高度:安卓:48px,iOS:44px
  • 单位必需跟胶囊按钮一致,用px

话不多说,上代码(gitHub地址):
js:

Component({ 
 properties: { 
 background: {  
 type: String,  
 value: 'rgba(255, 255, 255, 1)' 
 }, 
 color: {  
 type: String,  
 value: 'rgba(0, 0, 0, 1)' 
 }, 
 titleText: {  
 type: String,  
 value: '导航栏' 
 }, 
 titleImg: {  
 type: String,  
 value: '' 
 }, 
 backIcon: {  
 type: String,  
 value: '' 
 }, 
 homeIcon: {  
 type: String,  
 value: '' 
 }, 
 fontSize: {  
 type: Number,  
 value: 16 
 }, 
 iconHeight: {  
 type: Number,  
 value: 19 
 }, 
 iconWidth: {  
 type:Number,  
 value: 58 
 } 
 }, 
attached: function(){ 
 var that = this; 
 that.setNavSize(); 
 that.setStyle(); 
}, 
 data: {
 }, 
methods: { 
// 通过获取系统信息计算导航栏高度 
setNavSize: function() {  
var that = this  
 , sysinfo = wx.getSystemInfoSync()  
 , statusHeight = sysinfo.statusBarHeight  
 , isiOS = sysinfo.system.indexOf('iOS') > -1  
 , navHeight;  
if (!isiOS) {  
 navHeight = 48;  
 } else {  
 navHeight = 44;  
}  
that.setData({  
 status: statusHeight,  
 navHeight: navHeight  
 }) 
}, 
setStyle: function() {  
 var that = this  
 , containerStyle  
 , textStyle  
 , iconStyle;  
 containerStyle = [  
 'background:' + that.data.background  
 ].join(';');  
 textStyle = [  
 'color:' + that.data.color,  
 'font-size:' + that.data.fontSize + 'px'  
 ].join(';');  
 iconStyle = [  
 'width: ' + that.data.iconWidth + 'px',  
 'height: ' + that.data.iconHeight + 'px'  
 ].join(';');  
 that.setData({  
  containerStyle: containerStyle,  
  textStyle: textStyle,  
  iconStyle: iconStyle  
 }) }, 
 // 返回事件 
back: function(){  
 wx.navigateBack({  
 delta: 1  
 })  
 this.triggerEvent('back', {back: 1}) 
}, 
home: function() {  
 this.triggerEvent('home', {}); 
 } 
 }})

wxml:

<view class='nav' style='height: {{status + navHeight}}px'> 
 <view class='status' style='height: {{status}}px;{{containerStyle}}'></view>    <view class='navbar' style='height:{{navHeight}}px;{{containerStyle}}'> <view class='back-icon' wx:if="{{backIcon}}" bindtap='back'>   <image src='{{backIcon}}'></image> 
  </view> 
 <view class='home-icon' wx:if="{{homeIcon}}" bindtap='home'>  
 <image src='{{homeIcon}}'></image> 
 </view> [链接描述][10]
 <view class='nav-icon' wx:if="{{titleImg}}">  
 <image src='{{titleImg}}' style='{{iconStyle}}'></image> 
 </view>
  <view class='nav-title' wx:if="{{titleText && !titleImg}}">
  <text style='{{textStyle}}'>{{titleText}}</text>
  </view>
 </view>
 </view>

wxss:

.navbar{
 position: relative
}
.back-icon, .home-icon{
 width: 28px;
 height: 100%;
 position: absolute; 
 transform: translateY(-50%); 
 top: 50%; 
 display: flex;
 }
.back-icon{ 
 left: 16px;
}
.home-icon{ 
 left: 44px
}
.back-icon image{ 
 width: 28px; 
 height: 28px; 
 margin: auto;
}
.home-icon image{ 
 width: 20px; 
 height: 20px; 
 margin: auto;
}
.nav-title, .nav-icon{ 
 position: absolute; 
 transform: translate(-50%, -50%); 
 left: 50%; 
 top: 50%; 
 font-size: 0; 
 font-weight: bold;
}

运行效果图:

小程序实现自定义导航栏适配完美版

文字标题:

小程序实现自定义导航栏适配完美版

图片标题:

小程序实现自定义导航栏适配完美版

4、总结

经过小灰的一番论证以及实践经验,最终总结出以上最终解决方案,但希望对小伙伴们有所帮助,如果小伙伴们觉得有用,记得给颗star哦 --> 点我,后续还会更新其他组件。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jQuery文本框(input textare)事件绑定方法教程
Apr 24 Javascript
JQuery与JS里submit()的区别示例介绍
Feb 17 Javascript
js 获取、清空input type=&quot;file&quot;的值示例代码
Feb 19 Javascript
DOM操作一些常用的属性汇总
Mar 13 Javascript
JSP基于Bootstrap分页显示实例解析
Jun 12 Javascript
js导出excel文件的简洁方法(推荐)
Nov 02 Javascript
vue.js中Vue-router 2.0基础实践教程
May 08 Javascript
mui开发中获取单选按钮、复选框的值(实例讲解)
Jul 24 Javascript
Vue实现仿iPhone悬浮球的示例代码
Mar 13 Javascript
JavaScript cookie原理及使用实例
May 08 Javascript
JS typeof fn === 'function' &amp;&amp; fn()详解
Aug 22 Javascript
AJAX实现指定部分页面刷新效果
Oct 16 Javascript
es6 symbol的实现方法示例
Apr 02 #Javascript
微信小程序设置全局请求URL及封装wx.request请求操作示例
Apr 02 #Javascript
Vue CLI 3.x 自动部署项目至服务器的方法
Apr 02 #Javascript
Vue 组件修改根实例的数据的方法
Apr 02 #Javascript
vue鼠标悬停事件实例详解
Apr 01 #Javascript
jquery简单实现纵向的无缝滚动代码实例
Apr 01 #jQuery
详解Vue前端对axios的封装和使用
Apr 01 #Javascript
You might like
php读取javascript设置的cookies的代码
2010/04/12 PHP
PHP中header函数的用法及其注意事项详解
2016/06/13 PHP
createTextRange()的使用示例含文本框选中部分文字内容
2014/02/24 Javascript
JsRender for index循环索引用法详解
2014/10/31 Javascript
JavaScript 学习笔记之操作符(续)
2015/01/14 Javascript
jQuery实现冻结表头的方法
2015/03/09 Javascript
jquery利用命名空间移除绑定事件的方法
2015/03/11 Javascript
js实现超简单的展开、折叠目录代码
2015/08/28 Javascript
基于js实现checkbox批量选中操作
2016/11/22 Javascript
Three.js获取鼠标点击的三维坐标示例代码
2017/03/24 Javascript
JS实现移动端判断上拉和下滑功能
2017/08/07 Javascript
js 提取某()特殊字符串长度的实例
2017/12/06 Javascript
vuex 使用文档小结篇
2018/01/11 Javascript
vue webpack打包优化操作技巧
2018/02/22 Javascript
layui点击按钮添加可编辑的一行方法
2018/08/15 Javascript
Angular实现svg和png图片下载实现
2019/05/05 Javascript
原生js实现照片墙效果
2020/10/13 Javascript
vue+iview实现文件上传
2020/11/17 Vue.js
[01:33:30]DOTA2-DPC中国联赛 正赛 RNG vs Phoenix BO3 第二场 2月5日
2021/03/11 DOTA
跟老齐学Python之数据类型总结
2014/09/24 Python
详解Python使用tensorflow入门指南
2018/02/09 Python
对pyqt5中QTabWidget的相关操作详解
2019/06/21 Python
Python通过4种方式实现进程数据通信
2020/03/12 Python
新手学python应该下哪个版本
2020/06/11 Python
为什么说python更适合树莓派编程
2020/07/20 Python
Python paramiko使用方法代码汇总
2020/11/20 Python
canvas实现圆绘制的示例代码
2019/09/11 HTML / CSS
JD Sports意大利:英国篮球和运动时尚的领导者
2017/10/29 全球购物
美国最大的在线生存商店:Survival Frog
2020/12/13 全球购物
通用C#笔试题附答案
2016/11/26 面试题
自我鉴定范文
2013/11/10 职场文书
十佳青年个人事迹材料
2014/01/28 职场文书
家长学校教学计划
2015/01/19 职场文书
事业单位聘任报告
2015/03/02 职场文书
在CSS中使用when/else的方法
2022/01/18 HTML / CSS
MySQL示例讲解数据库约束以及表的设计
2022/06/16 MySQL