微信小程序自定义导航栏

背景

在作快狗打车小程序时,关于默认导航栏,咱们遇到了如下的问题:html

  1. Android、IOS手机对于页面title的展现不一致,安卓title的显示不居中
  2. 页面的title只支持纯文本级别的样式控制,不可以作更丰富的title效果
  3. 左上角的事件没法监听、定制
  4. 路由导航单一,只可以返回上一页,深层级页面的返回不够友好

咱们但愿的是:在各个机型页面上title一致性 & 个性化展现、取得左上角点击事件控制权及深层级页面的一键返回web

实现

step1 自定义

第一步 取得导航栏的控制权json

小程序支持自定义导航栏,只须要在app.json文件中,window项中配置小程序

"navigationStyle": "custom"
复制代码

这样微信就放开了导航栏的控制权,只保留右上角的胶囊。微信

页面会从视窗的顶部开始渲染,如图app

custom样式

接下来,咱们要作的就是实现一个导航栏组件,把它放置在页面原来的默认导航栏的位置,内容什么的彻底由开发者本身定制。函数

step2 功能点

第二步 梳理导航栏的功能点工具

  • 导航栏高度(各个机型动态适配)
  • 导航栏内容定制
    • 全部机型title居中显示(本身布局实现)
    • 首页导航栏左上角显示我的中心、中部title使用个性图标
    • 嵌套页面左上角显示返回上一页 + 回到首页按钮
    • 很是规首页左上角显示回到首页按钮

导航栏高度 包含两个部分:工具栏和title栏, 工具栏的高度通常是固定的20px,title栏的高度须要计算布局

导航栏内容的定制,须要识别当前页面的性质,根据不一样的页面展现不一样的内容,能够经过获取当前的页面路由栈来断定当前的页面性质spa

导航栏组件功能拆分

step3 导航栏组件基本结构

目前快狗打车小程序的基本结构

// navBar.wxml
<cover-view class='place-holder'></cover-view>
<cover-view class='nav-bar'>
    <cover-view class='tool-bar' style='height: 20px'></cover-view>
    <cover-view class='title-bar'>
        <cover-view class='left-cell'>
            // scene0 常规首页   我的中心按钮
            // scene1 很是规首页 回首页按钮
            // scene2 嵌套页     返回上一页按钮 + 回首页按钮
        </cover-view>
        <cover-view class='center-cell'>
            // scene0 常规首页  个性化title
            // scene1 其余页    正常title
        </cover-view>
        <cover-view class='right-cell'>
            // 占位用的
        </cover-view>
    </cover-view>
</cover-view>
复制代码

Tips

  • 组件内多了一个占位的place-holder块,是由于某些页面有相似滚动列表的需求,要保证导航栏始终在视窗的顶部的话,须要使用定位,定位以后脱离文档流,在最初的时候须要占位块保证后续的页面内容不会被导航栏遮挡
  • 使用cover-view布局是由于快狗的业务中有相似map的原生组件,使用view的话有被遮挡的风险

step4 高度计算

须要计算title-bar的高度

在 默认导航栏 & 无底部tab栏 的状况下,使用wx.getSystemInfoSync获取手机信息,能够看到两项信息:

  • screenHeight 屏幕高度,单位px
  • windowHeight 可以使用窗口高度,单位px

这种状况下,两者的差值就是默认的导航栏的高度, 可是在设置了"navigationStyle": "custom"以后,两者的值是同样的了,所以导航栏的高度咱们须要使用统计的经验值。

根据统计,获得以下的结果:

{
    'iPhone': 64,
    'iPhoneX': 88,
    'Android': 68,
    'samsung': 72
}
复制代码

工具栏的高度可根据wx.getSystemInfoSync返回值中的statusBarHeight获取。

至此,咱们获得了导航栏的相关的高度值

// 导航栏总高度 & 占位块高度
placeHoder = totalBar = {
    'iPhone': 64,
    'iPhoneX': 88,
    'Android': 68,
    'samsung': 72
}
// 时间、信号等工具栏的高度
toolBar = systermInfo.statusBarHeight
// 页面title栏的高度
titleBar = totalBar - toolBar
复制代码

step5 内容定制

在组件的生命周期函数attached中,咱们能够获取当前的页面路由栈

let pages = getCurrentPages()
let current_page = pages[pages.length - 1].route 
const NORMAL_ENTRY = '常规的入口页路径'

// scene 0 常规入口页 个性化title、我的中心
pages.length === 1 && current_page === NORMAL_ENTRY
// scene 1 很是规入口页 回首页
pages.length === 1 && current_page !== NORMAL_ENTRY
// scene 2 嵌套页面 返回 + 回首页
pages.length > 1 
    
复制代码

根据不一样的条件,展现不一样的内容

最终效果

scene 0 常规首页

image

scene 1 很是规首页

image

scene 2 嵌套页

image

目前在生产环境99%的机型中,均可以完美的运行。

写在最后

  • 自定义导航栏是全局生效的,一旦设置,各个原生小程序页面都须要引入
  • 目前微信版本7+支持了针对特定页面的自定义导航栏,能够根据须要个性化定制
  • 自定义导航栏在web-view页面不会起效
  • 有尝试把导航栏作成插件,可是遇到在插件组件中没法获取页面路由栈的问题,所以没有成功
相关文章
相关标签/搜索