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


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之Document元素选择器篇
Aug 14 Javascript
iframe的onload在Chrome/Opera中执行两次Bug的解决方法
Mar 17 Javascript
点击隐藏页面左栏或右栏实现js代码
Apr 01 Javascript
jquery仿京东导航/仿淘宝商城左侧分类导航下拉菜单效果
Apr 24 Javascript
node.js中的fs.readlink方法使用说明
Dec 17 Javascript
js+canvas简单绘制圆圈的方法
Jan 28 Javascript
通过BootStrap实现轮播图的实际应用
Sep 26 Javascript
jQuery实现鼠标滑过预览图片大图效果的方法
Apr 26 jQuery
vue mixins组件复用的几种方式(小结)
Sep 06 Javascript
node.js中使用Export和Import的方法
Sep 18 Javascript
Node.js 在本地生成日志文件的方法
Feb 07 Javascript
Node.js 中判断一个文件是否存在
Aug 24 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实现的随机广告显示代码
2007/06/14 PHP
PHP If Else(elsefi) 语句
2013/04/07 PHP
浅析关于PHP位运算的简单权限设计
2013/06/30 PHP
PHP中的插件机制原理和实例
2014/07/08 PHP
PHP获取网页所有连接的方法(附demo源码下载)
2016/03/30 PHP
一行代码告别document.getElementById
2012/06/01 Javascript
javascript检测浏览器的缩放状态实现代码
2014/09/28 Javascript
浅谈Javascript实现继承的方法
2015/07/06 Javascript
js实现滚动条滚动到某个位置便自动定位某个tr
2021/01/20 Javascript
JavaScript html5 canvas绘制时钟效果(二)
2016/03/27 Javascript
浅谈Javascript数据属性与访问器属性
2016/07/26 Javascript
利用原生js和jQuery实现单选框的勾选和取消操作的方法
2016/09/04 Javascript
jquery遍历标签中自定义的属性方法
2016/09/17 Javascript
javascript中this用法实例详解
2017/04/06 Javascript
vue-cli + sass 的正确打开方式图文详解
2017/10/27 Javascript
vue项目中的webpack-dev-sever配置方法
2017/12/14 Javascript
浅析JavaScript中的特殊数据类型
2017/12/15 Javascript
详解ES6 系列之异步处理实战
2018/10/26 Javascript
React 组件渲染和更新的实现代码示例
2019/02/21 Javascript
vue-cli脚手架的.babelrc文件用法说明
2020/09/11 Javascript
python django集成cas验证系统
2014/07/14 Python
python 用所有标点符号分隔句子的示例
2019/07/15 Python
利用Pandas和Numpy按时间戳将数据以Groupby方式分组
2019/07/22 Python
在Python中使用filter去除列表中值为假及空字符串的例子
2019/11/18 Python
利用Python的sympy包求解一元三次方程示例
2019/11/22 Python
解决python运行效率不高的问题
2020/07/20 Python
python 使用tkinter+you-get实现视频下载器
2020/11/17 Python
Mankind美国/加拿大:英国领先的男士美容护发用品公司
2018/12/05 全球购物
拾金不昧表扬信范文
2014/01/11 职场文书
金融管理专业毕业生求职信
2014/03/12 职场文书
农村面貌改造提升实施方案
2014/03/18 职场文书
食品安全工作方案
2014/05/07 职场文书
安全生产工作汇报
2014/10/28 职场文书
2016年小学生教师节广播稿
2015/12/18 职场文书
win10如何快速切换窗口 win10切换窗口快捷键分享
2022/07/23 数码科技
Win11无法安装更新补丁KB3045316怎么办 附KB3045316补丁修复教程
2022/08/14 数码科技