微信小程序自定义导航栏组件(完美适配所有手机),可自定义实现任何你想要的功能
背景
在做小程序時(shí),關(guān)于默認(rèn)導(dǎo)航欄,我們遇到了以下的問(wèn)題:
- Android、IOS 手機(jī)對(duì)于頁(yè)面 title 的展示不一致,安卓 title 的顯示不居中
- 頁(yè)面的 title 只支持純文本級(jí)別的樣式控制,不能夠做更豐富的 title 效果
- 左上角的事件無(wú)法監(jiān)聽(tīng)、定制
- 路由導(dǎo)航單一,只能夠返回上一頁(yè),深層級(jí)頁(yè)面的返回不夠友好
探索
小程序自定義導(dǎo)航欄已開(kāi)放許久>>了解一下,相信不少小伙伴已使用過(guò)這個(gè)功能,同時(shí)不少小伙伴也會(huì)發(fā)現(xiàn)一些坑:
- 機(jī)型多如牛毛:自定義導(dǎo)航欄高度在不同機(jī)型始終無(wú)法達(dá)到視覺(jué)上的統(tǒng)一
- 導(dǎo)航欄中內(nèi)容怎么都不垂直居中對(duì)齊,更別說(shuō)適配所有手機(jī)
- 調(diào)皮的膠囊按鈕:導(dǎo)航欄元素(文字,圖標(biāo)等)怎么也對(duì)不齊那該死的膠囊按鈕
- 各種尺寸的全面屏,奇怪的劉海屏,簡(jiǎn)直要抓狂
一探究竟
為了搞明白原理,我先去翻了官方文檔,>>飛機(jī),點(diǎn)過(guò)去是不是很驚喜,很意外,通篇大文盡然只有最下方的一張圖片與這個(gè)問(wèn)題有關(guān),并且啥也看不清,汗汗汗…
我特意找了一張圖片來(lái)
分析上圖,我得到如下信息:
- Android 跟 iOS 有差異,表現(xiàn)在頂部到膠囊按鈕之間的距離差了 6pt
- 膠囊按鈕高度為 32pt, iOS 和 Android 一致
動(dòng)手分析
我們寫(xiě)一個(gè)狀態(tài)欄,通過(guò) wx.getSystemInfoSync().statusBarHeight 設(shè)置高度
Android:
iOS:
可以看出,iOS 膠囊按鈕與狀態(tài)欄之間距離為:4px, Android 為 8px,是不是所有手機(jī)都是這種情況呢?
答案是:蘋(píng)果手機(jī)確實(shí)都是 4px,安卓大部分都是 7 和 8 也會(huì)有其他的情況(可以自己打印 getSystemInfo 驗(yàn)證)如何快速便捷算出這個(gè)高度,請(qǐng)接著往下看
如何計(jì)算
導(dǎo)航欄分為狀態(tài)欄和標(biāo)題欄,只要能算出每臺(tái)手機(jī)的導(dǎo)航欄高度問(wèn)題就迎刃而解
- 導(dǎo)航欄高度 = 膠囊按鈕高度 + 狀態(tài)欄到膠囊按鈕間距 * 2 + 狀態(tài)欄高度
注:由于膠囊按鈕是原生組件,為表現(xiàn)一致,其單位在各種手機(jī)中都為 px,所以我們自定義導(dǎo)航欄的單位都必需是 px(切記不能用 rpx),才能完美適配。
解決問(wèn)題
現(xiàn)在我們明白了原理,可以利用膠囊按鈕的位置信息和 statusBarHeight 高度動(dòng)態(tài)計(jì)算導(dǎo)航欄的高度,貼一個(gè)實(shí)現(xiàn)此功能最重要的方法
let systemInfo = wx.getSystemInfoSync();
let rect = wx.getMenuButtonBoundingClientRect ? wx.getMenuButtonBoundingClientRect() : null; //膠囊按鈕位置信息wx.getMenuButtonBoundingClientRect();let navBarHeight = (function() { //導(dǎo)航欄高度let gap = rect.top - systemInfo.statusBarHeight; //動(dòng)態(tài)計(jì)算每臺(tái)手機(jī)狀態(tài)欄到膠囊按鈕間距return 2 * gap + rect.height;})();
gap 信息就是不同的手機(jī)其狀態(tài)欄到膠囊按鈕間距,具體更多代碼實(shí)現(xiàn)和使用 demo 請(qǐng)移步下方代碼倉(cāng)庫(kù),代碼中還會(huì)有輸入框文字跳動(dòng)解決辦法,安卓手機(jī)輸入框文字飛出解決辦法,左側(cè)按鈕邊框太粗解決辦法等等
膠囊信息報(bào)錯(cuò)和獲取不到
問(wèn)題就在于 getMenuButtonBoundingClientRect 這個(gè)方法,在某些機(jī)子和環(huán)境下會(huì)報(bào)錯(cuò)或者獲取不到,對(duì)于此種情況完美可以模擬一個(gè)膠囊位置出來(lái)
try {rect = Taro.getMenuButtonBoundingClientRect ? Taro.getMenuButtonBoundingClientRect() : null;if (rect === null) {throw 'getMenuButtonBoundingClientRect error';}//取值為0的情況if (!rect.width) {throw 'getMenuButtonBoundingClientRect error';}
} catch (error) {let gap = ''; //膠囊按鈕上下間距 使導(dǎo)航內(nèi)容居中l(wèi)et width = 96; //膠囊的寬度,android大部分96,ios為88if (systemInfo.platform === 'android') {gap = 8;width = 96;} else if (systemInfo.platform === 'devtools') {if (ios) {gap = 5.5; //開(kāi)發(fā)工具中ios手機(jī)} else {gap = 7.5; //開(kāi)發(fā)工具中android和其他手機(jī)}} else {gap = 4;width = 88;}if (!systemInfo.statusBarHeight) {//開(kāi)啟wifi的情況下修復(fù)statusBarHeight值獲取不到systemInfo.statusBarHeight = systemInfo.screenHeight - systemInfo.windowHeight - 20;}rect = {//獲取不到膠囊信息就自定義重置一個(gè)bottom: systemInfo.statusBarHeight + gap + 32,height: 32,left: systemInfo.windowWidth - width - 10,right: systemInfo.windowWidth - 10,top: systemInfo.statusBarHeight + gap,width: width};console.log('error', error);console.log('rect', rect);
}
以上代碼主要是借鑒了拼多多的默認(rèn)值寫(xiě)法,android 機(jī)子中 gap 值大部分為 8,ios 都為 4,開(kāi)發(fā)工具中 ios 為 5.5,android 為 7.5,這樣處理之后自己模擬一個(gè)膠囊按鈕的位置,這樣在獲取不到膠囊信息的情況下,可保證絕大多數(shù)機(jī)子完美顯示導(dǎo)航頭
吐槽
這么重要的問(wèn)題,官方盡然沒(méi)有提供解決方案…竟然提供了一張看不清的圖片???
網(wǎng)上有很多 ios 設(shè)置 44,android 設(shè)置 48,還有根據(jù)不同的手機(jī)型號(hào)設(shè)置不同高度,通過(guò)長(zhǎng)時(shí)間的開(kāi)發(fā)和嘗試,本人發(fā)現(xiàn)以上方案并不完美,并且 bug 很多
代碼庫(kù)
- Taro 組件gitHub 地址詳細(xì)用法請(qǐng)參考 README
- 原生組件 npm 構(gòu)建版本gitHub 地址詳細(xì)用法請(qǐng)參考 README
- 原生組件簡(jiǎn)易版gitHub 地址詳細(xì)用法請(qǐng)參考 README
- 由于本人精力有限,目前只計(jì)劃發(fā)布維護(hù)好這 2 種組件,其他組件請(qǐng)自行修改代碼,有問(wèn)題請(qǐng)聯(lián)系
備注
- 上方 2 種組件在最下方 30 多款手機(jī)測(cè)試情況表現(xiàn)良好
- iPhone 手機(jī)打電話和開(kāi)熱點(diǎn)導(dǎo)致導(dǎo)航欄樣式錯(cuò)亂,問(wèn)題已經(jīng)解決啦,請(qǐng)去 demo 里測(cè)試,這里特別感謝 moments 網(wǎng)友提出的問(wèn)題
- 本文章并無(wú)任何商業(yè)性質(zhì),如有侵權(quán)請(qǐng)聯(lián)系本人修改或刪除
- 文章少量部分內(nèi)容是本人查詢搜集而來(lái)
- 如有問(wèn)題可以下方留言討論,微信 zhijunxh
比較
斗魚(yú):
虎牙:
微博:
酷狗:
知乎:
知乎是這里邊做的最好的,但是我個(gè)人認(rèn)為有幾個(gè)可以優(yōu)化的小問(wèn)題
- 打電話或者開(kāi)啟熱點(diǎn)導(dǎo)致樣式錯(cuò)落,這也是大部門(mén)小程序的問(wèn)題
- 導(dǎo)航欄下邊距太小,看起來(lái)不舒服
- 搜索框距離 2 側(cè)按鈕組距離不對(duì)等
- 自定義返回和 home 按鈕中的豎線顏色重了,并且感覺(jué)太粗
如果您看到了此篇文章,請(qǐng)趕快修改自己的代碼,并運(yùn)用在實(shí)踐中吧
掃碼體驗(yàn)我的小程序:
創(chuàng)作不易,如果對(duì)你有幫助,請(qǐng)移步 Taro 組件gitHub原生組件gitHub給個(gè)星星 star✨✨ 謝謝
測(cè)試信息
| 手機(jī)型號(hào) | 膠囊位置信息 | statusBarHeight | 測(cè)試情況 |
|---|---|---|---|
| iPhoneX | 80 32 281 369 48 88 | 44 | 通過(guò) |
| iPhone8 plus | 56 32 320 408 24 88 | 20 | 通過(guò) |
| iphone7 | 56 32 281 368 24 87 | 20 | 通過(guò) |
| iPhone6 plus | 56 32 320 408 24 88 | 20 | 通過(guò) |
| iPhone6 | 56 32 281 368 24 87 | 20 | 通過(guò) |
| HUAWEI SLA-AL00 | 64 32 254 350 32 96 | 24 | 通過(guò) |
| HUAWEI VTR-AL00 | 64 32 254 350 32 96 | 24 | 通過(guò) |
| HUAWEI EVA-AL00 | 64 32 254 350 32 96 | 24 | 通過(guò) |
| HUAWEI EML-AL00 | 68 32 254 350 36 96 | 29 | 通過(guò) |
| HUAWEI VOG-AL00 | 65 32 254 350 33 96 | 25 | 通過(guò) |
| HUAWEI ATU-TL10 | 64 32 254 350 32 96 | 24 | 通過(guò) |
| HUAWEI SMARTISAN OS105 | 64 32 326 422 32 96 | 24 | 通過(guò) |
| XIAOMI MI6 | 59 28 265 352 31 87 | 23 | 通過(guò) |
| XIAOMI MI4LTE | 60 32 254 350 28 96 | 20 | 通過(guò) |
| XIAOMI MIX3 | 74 32 287 383 42 96 | 35 | 通過(guò) |
| REDMI NOTE3 | 64 32 254 350 32 96 | 24 | 通過(guò) |
| REDMI NOTE4 | 64 32 254 350 32 96 | 24 | 通過(guò) |
| REDMI NOTE3 | 55 28 255 351 27 96 | 20 | 通過(guò) |
| REDMI 5plus | 67 32 287 383 35 96 | 28 | 通過(guò) |
| MEIZU M571C | 65 32 254 350 33 96 | 25 | 通過(guò) |
| MEIZU M6 NOTE | 62 32 254 350 30 96 | 22 | 通過(guò) |
| MEIZU MX4 PRO | 62 32 278 374 30 96 | 22 | 通過(guò) |
| OPPO A33 | 65 32 254 350 33 96 | 26 | 通過(guò) |
| OPPO R11 | 58 32 254 350 26 96 | 18 | 通過(guò) |
| VIVO Y55 | 64 32 254 350 32 96 | 24 | 通過(guò) |
| HONOR BLN-AL20 | 64 32 254 350 32 96 | 24 | 通過(guò) |
| HONOR NEM-AL10 | 59 28 265 352 31 87 | 24 | 通過(guò) |
| HONOR BND-AL10 | 64 32 254 350 32 96 | 24 | 通過(guò) |
| HONOR duk-al20 | 64 32 254 350 32 96 | 24 | 通過(guò) |
| SAMSUNG SM-G9550 | 64 32 305 401 32 96 | 24 | 通過(guò) |
| 360 1801-A01 | 64 32 254 350 32 96 | 24 | 通過(guò) |
總結(jié)
以上是生活随笔為你收集整理的微信小程序自定义导航栏组件(完美适配所有手机),可自定义实现任何你想要的功能的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: LG P4198 楼房重建(线段树)
- 下一篇: 会员限时返场合集:QQ 全系 5 折购,