微信小程序自定義導航欄

背景

在作快狗打車小程序時,關於默認導航欄,咱們遇到了如下的問題: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頁面不會起效
  • 有嘗試把導航欄作成插件,可是遇到在插件組件中沒法獲取頁面路由棧的問題,所以沒有成功
相關文章
相關標籤/搜索