这篇文章主要介绍了小程序实现自定义导航栏适配完美版,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

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>
    <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哦 


上一篇:linux系统安装FFmpeg的步骤教程

下一篇:css3 flex 详解,可以实现div内容水平垂直居中

评论列表
发表评论
称呼
邮箱
网址
验证码(*)
热评文章
相关阅读