注册
web

小程序自定义导航栏

小程序布局




  • 谈到导航栏与自定义导航栏,就需要解释一下微信小程序的布局了。在小程序开发中使用wx.getSystemInfoAsync() 方法可以获取到系统信息。


    image.png


    image.png




  • 部分获取到的信息如上图(截取自微信小程序开发者文档),对我们理解布局有用的信息是以上跟宽度高度相关的属性,如当前设备的屏幕高宽,可用高宽,以及saveArea





  • 上图展示我们从systemInfo获取到的数据的实际表现,以苹果X的刘海屏为例(所有安卓刘海屏原理类似):最外层的红色框即屏幕大小,蓝色框即安全区域字面意思也就是开发者所能操纵的页面区域,上面的黄色框即手机的状态栏,绿色区域即我们要自定义的navigationBar




  • 可见,导航栏紧贴safeArea的上部,如果使用原生导航栏,导航栏下方即是真正意义的可操控范围。




  • 实际上我们自定义的导航栏也是在这个safeArea内与胶囊对齐最为和谐。很关键的原因就是微信将右上角的胶囊按钮作为了内置组件,只有黑白两种颜色,即我们无法改变它的大小位置透明度等等,所以为了配合胶囊按钮,一般自定义的导航栏位置也与上图位置一致。




自定义navigationBar怎么做?


去掉原生导航栏。



  1. 将需要自定义navigationBar页面的page.json的navigationBarTitleText去掉。
  2. 加上 "navigationStyle":"custom" ,这样原生的导航栏就已经消失,甚至后退键也不会出现需要自定义。
  3. 另外,早在2016年微信已经开始适配沉浸式状态栏,目前几乎所有的机型里微信都是沉浸式状态栏,也就是说去掉原生导航栏的同时,整个屏幕已经成为可编程区域

计算navigationBarHeight。



  • 原生的胶囊按钮当然存在,那么下一步就需要你去定位出自定义的导航栏高度以及位置。
  • 对于不同的机型,对于不同的系统,状态栏以及胶囊按钮的位置都不确定,所以需要用到一定的计算,从而面对任何机型都可以从容判定。



  1. 使用wx.getSystemInfoSync() 获取到statusBarHeight,这样就确定了导航栏最基本的距离屏幕上方的距离。




  2. 使用wx.getMenuButtonBoundingClientRect() 获取到小程序的胶囊信息(注意这个api存在各种问题,在不同端表现不一致,后面会叙述这个api调用失败的处理情况),如下图,以下坐标信息以屏幕左上角为原点。





  3. 以下图为例,上面的红色框是statusBar,高度已知;下面的红色框是正文内容,夹在中间的就是求解之一navigationBarHeight;而黄色的是原生胶囊按钮也是在垂直居中位置,高度为胶囊按钮基于左上角的坐标信息已知,不难得出,navigationBarHeight = 蓝色框高度 × 2 + 胶囊按钮.height。(蓝色框高度 = 胶囊按钮.top - statusBarHeight






  1. 最后的计算公式为:navigationBarHeight = (胶囊按钮.top - statusBarHeight) × 2 + 胶囊按钮.height。navigationBar 距屏幕上方的距离即为navigationBarHeight
  2. 这种计算方法在各种机型以及安卓ios都适用。
  3. 针对"wx.getMenuButtonBoundingClientRect() "获取错误或者获取数据为0的极少数情况,只能够去模拟,对于android,一般navigationBarHeight为48px,而对于ios一般为40px,所有机型的胶囊按钮高度是32px。


代码实现



  • 获取本机信息,写在组件的attached生命周期中。

// components/Navigation/index.js
Component({
/**
* 组件的属性列表
*/

properties: {

},

/**
* 组件的初始数据
*/

data: {
navigationBarHeight: 40,
statusBarHeight:20,
},

/**
* 组件的方法列表
*/

methods: {

},
lifetimes: {
attached: function () {
const { statusBarHeight, platform } = wx.getSystemInfoSync();
const { top, height = 32 } = wx.getMenuButtonBoundingClientRect();// 胶囊按钮高度 一般是32 如果获取不到就使用32
// 判断胶囊按钮信息是否成功获取
if (top && top !== 0 && height && height !== 0) {
//获取成功进行计算
const navigationBarHeight = (top - statusBarHeight) * 2 + height;
console.log(navigationBarHeight)
// 导航栏高度
this.setData({
navigationBarHeight,
statusBarHeight
})
} else {
//获取失败使用默认的高度
this.setData({
navigationBarHeight: platform === "android" ? 48 : 40,
statusBarHeight
})
}
}
}
})



  • 组件模板编写

<view class="custom-nav" style="height: {{navigationBarHeight}}px;margin-top:{{statusBarHeight}}px;">
<view>
<image style="width: 40rpx;height:40rpx;" src="/images/location.svg" mode="" />
</view>
</view>


 .navigationBar.wxml 样式如下:


.custom-nav{
background-color:palegoldenrod;
display: flex;
align-items: center;
}
.custom-nav__title{
margin:auto
}

外部页面引用该组件如下,


.json文件,引入组件


{
"usingComponents": {
"my-navigation":"/components/Navigation"
},
"navigationStyle": "custom"
}

注意添加属性:"navigationStyle":"custom"  代表我们要自定义组件


.wxml代码如下:


<view>
<my-navigation></my-navigation>
<view class="page-container" style="background-color: rebeccapurple;">这里是页面内容</view>
</view>


最终效果
image.png


如果想要编写更加通用的组件,可以根据需求定义传入的参数和样式


参考链接


http://www.cnblogs.com/chenwo

作者:let_code
来源:juejin.cn/post/7254812719349858361
long/…

0 个评论

要回复文章请先登录注册