1、发现问题
小程序页面自定义导航栏功能已经开放有些日子了(还不知道这个功能的可以先 >>了解一下 ),这极大的提升了小程序开发的自由度,相信不少小伙伴已经使用过这个功能,同时也相信不少小伙伴在此功能开发过程中踩过同样的一些坑:
同样的,这些问题也是小灰经历过的。但是小灰相信,办法总比问题多,于是开始了自己的探究:
2、一探究竟
为了搞明白到底该怎么去适配,老规矩,我先翻了一波官方文档,还别说,官方还真有这么一段介绍了相关细节, >>详情点击 :
从图中分析,我们可以得到如下信息:
- Android跟iOS有差异,表现在顶部到胶囊按钮之间的距离差了6pt
- 胶囊按钮高度为32pt, iOS和Android一致
这。。。,好像并没有什么L用啊??这仅仅是普通屏幕为参照的,ipx, 安卓全面屏完全没介绍。
沉着冷静,我们接着分析:
那么我们来论证一下:
第一个问题:胶囊按钮到状态栏下边缘的距离是不是固定的?
很简单,我们写一个状态栏,通过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
js:
Component({
properties: {
background: {
type: String,value: 'rgba(255,255,1)'
},color: {
'rgba(0,titleText: {
'导航栏'
},titleImg: {
''
},backIcon: {
''
},homeIcon: {
Number,value: 16
},iconHeight: {
19
},iconWidth: {
type:58
}
},attached: function(){
var that = this;
that.setNavSize();
that.setStyle();
},data: {
},methods: {
// 通过获取系统信息计算导航栏高度
setNavSize: function() {
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 = 'background:' + that.data.background
].join(';');
textStyle = [
'color:' + that.data.color,'font-size:' + that.data.fontSize + 'px'
].join(';');
iconStyle = [
'width: ' + that.data.iconWidth + 'px',0);">'height: ' + that.data.iconHeight + ';');
that.setData({
containerStyle: containerStyle,textStyle: textStyle,iconStyle: iconStyle
}) },// 返回事件
back: function(){
wx.navigateBack({
delta: 1
})
this.triggerEvent('back',{back: 1})
},home: 'home',{});
}
}})
wxml:
<view class='nav' style='height: {{status + navHeight}}px'>
<'status' style={{status}}px;{{containerStyle}}'></view> <'navbar' style='height:{{navHeight}}'> <'back-icon' wx:if="{{backIcon}}" bindtap='back'> <image src='image>
</view>
<'home-icon' wx:if={{homeIcon}'home'>
<image>
</view> [链接描述][10]
<'nav-icon' wx:if={{titleImg}}">
<}' style={{iconStyle}image>
</view>
<'nav-title' wx:if={{titleText && !titleImg}}">
<text style={{textStyle}}'>{{titleText}}</text>
</view>
</view>
</view>
wxss:
运行效果图:4、总结
经过小灰的一番论证以及实践经验,最终总结出以上最终解决方案,但希望对小伙伴们有所帮助,如果小伙伴们觉得有用,记得给颗star哦 --> 点我 ,后续还会更新其他组件。
如果大家有更好的方案或者觉得小灰的方案有问题,欢迎大家留言。