小程序实现自定义导航栏适配完美版
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哦 --> ,后续还会更新其他组件。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。