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


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 相关文章推荐
ExtJs grid行 右键菜单的两种方法
Jun 19 Javascript
基于jquery的可多选的下拉列表框
Jul 20 Javascript
jquery无缝向上滚动实现代码
Mar 29 Javascript
JavaScript中的prototype.bind()方法介绍
Apr 04 Javascript
解决jQuery动态获取手机屏幕高和宽的问题
May 07 Javascript
深入理解JavaScript系列(48):对象创建模式(下篇)
Mar 04 Javascript
ajax级联菜单实现方法实例分析
Nov 28 Javascript
bootstrap为水平排列的表单和内联表单设置可选的图标
Feb 15 Javascript
教你5分钟学会用requirejs(必看篇)
Jul 25 Javascript
BACKBONE.JS 简单入门范例
Oct 17 Javascript
jQuery第一次运行页面默认触发点击事件的实例
Jan 10 jQuery
javascript实现一款好看的秒表计时器
Sep 05 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将时间差转换为字符串提示
2011/09/07 PHP
php断点续传之文件分割合并详解
2016/12/13 PHP
ThinkPHP 整合Bootstrap Ajax分页样式
2016/12/23 PHP
jquery multiSelect 多选下拉框
2010/07/09 Javascript
javascript控制swfObject应用介绍
2012/11/29 Javascript
window.event.keyCode兼容IE和Firefox实现js代码
2013/05/30 Javascript
基于jQuery实现的文字按钮表单特效整理
2014/12/07 Javascript
JavaScript中的继承方式详解
2015/02/11 Javascript
jQuery延迟加载图片插件Lazy Load使用指南
2015/03/25 Javascript
将页面table内容与样式另存成excel文件的方法
2015/08/05 Javascript
关于JavaScript数组你所不知道的3件事
2016/08/24 Javascript
Ubuntu 16.04 64位中搭建Node.js开发环境教程
2016/10/19 Javascript
jQuery 常见小例汇总
2016/12/14 Javascript
基于canvas的二维码邀请函生成插件
2017/02/14 Javascript
详解微信小程序用定时器实现倒计时效果
2019/04/30 Javascript
vue cli3.0 引入eslint 结合vscode使用
2019/05/27 Javascript
基于layui的下拉列表的数据回显方法
2019/09/24 Javascript
jQuery/JS监听input输入框值变化实例
2019/10/17 jQuery
八种Vue组件间通讯方式合集(推荐)
2020/08/18 Javascript
用Python登录Gmail并发送Gmail邮件的教程
2015/04/17 Python
Python探索之静态方法和类方法的区别详解
2017/10/27 Python
Python使用django框架实现多人在线匿名聊天的小程序
2017/11/29 Python
用python编写第一个IDA插件的实例
2018/05/29 Python
详解python Todo清单实战
2018/11/01 Python
python ipset管理 增删白名单的方法
2019/01/14 Python
python中的print()输出
2019/04/12 Python
Python3中列表list合并的四种方法
2019/04/19 Python
TensorFlow绘制loss/accuracy曲线的实例
2020/01/21 Python
Python实现微信表情包炸群功能
2021/01/28 Python
详解使用HTML5的classList属性操作CSS类
2017/10/13 HTML / CSS
瑞士领先的网上超市:LeShop.ch
2018/11/14 全球购物
毕业生自我鉴定
2013/11/05 职场文书
成功的餐厅经营创业计划书
2014/01/15 职场文书
企业党建工作汇报材料
2014/08/19 职场文书
利用python Pandas实现批量拆分Excel与合并Excel
2021/05/23 Python
如何使用 resize 实现图片切换预览功能
2021/08/23 HTML / CSS