詳解微信小程序膠囊按鈕返回|首頁自定義導(dǎo)航欄功能
項目代碼:https://github.com/Shay0921/header-navbar.git
在小程序中,從轉(zhuǎn)發(fā)出來的小程序消息卡片進入,因為頁面棧中只有一個,所以不會出現(xiàn)返回按鈕,對于一些電商平臺來說,當(dāng)商品被轉(zhuǎn)發(fā)后會很影響客戶查看其它產(chǎn)品和首頁,這時候就需要使用自定義導(dǎo)航欄自己寫一個“膠囊按鈕”。如下圖所示:
從別的頁面點到商品頁時會有返回和首頁按鈕;
當(dāng)從分享頁進入到商品頁時,因為頁面棧只有一個,所以只有首頁按鈕;
首先我們需要如何開啟自定義導(dǎo)航欄,查看手冊后會發(fā)現(xiàn)一個頁面配置項: navigationStyle
之前的版本此配置項只能在app.js中配置,是全局的屬性,而現(xiàn)在可以在單獨的頁面json中配置,實現(xiàn)單獨頁面自定義導(dǎo)航欄。
整體思路
當(dāng)使用了 navigationStyle:custom 后,之前的頂部標(biāo)題欄會被刪除,右側(cè)的膠囊按鈕則會固定在右上角。然后在當(dāng)前頁面添加了三個view(狀態(tài)欄、標(biāo)題欄、主體內(nèi)容),可以看出三塊的布局,我直接寫死的高度:狀態(tài)欄20px,標(biāo)題欄44px。這個是自定義導(dǎo)航欄的關(guān)鍵,需要去計算這兩塊的高度,還有返回|首頁膠囊按鈕的位置?;A(chǔ)庫 2.1.0開始可以使用 wx.getMenuButtonBoundingClientRect() 來獲得 右側(cè)膠囊按鈕的位置信息 ,而有了這個信息,就能相對的算出我們想要在左側(cè)添加的膠囊按鈕的位置。通過 wx.getSystemInfoSync()中的statusBarHeight找到狀態(tài)欄的高度 。
目錄結(jié)構(gòu)
├── components 組件 │ ├── headerNavbar 頂部自定義導(dǎo)航欄 │ │ └── headerNavbar.js │ │ └── headerNavbar.json │ │ └── headerNavbar.wxml │ │ └── headerNavbar.wxss ├── pages 頁面 │ ├── index 首頁 │ │ └── index.js │ │ └── index.json │ │ └── index.wxml │ │ └── index.wxss │ ├── navigationStyle 引入自定義導(dǎo)航欄的頁面(單獨配置了navigationStyle) │ │ └── navigationStyle.js │ │ └── navigationStyle.json │ │ └── navigationStyle.wxml │ │ └── navigationStyle.wxss │ │ └── testPage.js 路由測試頁面(后面用來測試跳轉(zhuǎn)顯示不同膠囊按鈕) │ │ └── testPage.json │ │ └── testPage.wxml │ │ └── testPage.wxss
全局變量
app.js
在app.js中要先獲得狀態(tài)欄高度和右側(cè)膠囊位置信息
App({
onLaunch: function (options) {
// 這里省略掉了登錄和獲取用戶信息等函數(shù)
// 因為我在別的頁面也需要使用此信息,所以沒有單獨獲得 statusBarHeight
wx.getSystemInfo({ // 獲取設(shè)備信息
success: (res) => {
this.globalData.systeminfo = res
},
})
// 獲得膠囊按鈕位置信息
this.globalData.headerBtnPosi = wx.getMenuButtonBoundingClientRect()
},
globalData: {
systeminfo: {}, // 系統(tǒng)信息
headerBtnPosi: {} // 膠囊按鈕位置信息
}
})
這里需要注意wx.getMenuButtonBoundingClientRect(),并不是像wx.getSystmInfo一樣有success回調(diào)函數(shù),而是像對象一樣 wx.getMenuButtonBoundingClientRect().height 來使用。
組件代碼
headerNavbar.wxml
<!-- 自定義導(dǎo)航欄 -->
<view class='navbar-wrap'
style='height:{{navbarHeight}}px;padding-top:{{statusBarHeight}}px;'>
<view class="navbar-text"
style='line-height:{{navbarBtn.height + navbarBtn.top}}px;'>
{{navbarData.title ? navbarData.title : "默認標(biāo)題"}}{{navbarHeight}}
</view>
<view class="navbar-icon"
wx:if='{{navbarData.showCapsule ? navbarData.showCapsule : true}}'
style="top:{{navbarBtn.top + statusBarHeight}}px;left:{{navbarBtn.right}}px;height:{{navbarBtn.height}}px;">
<image wx:if='{{haveBack}}' bindtap="_goBack" class="floatL" src="/img/navbar_back_white.png"></image>
<view wx:if='{{haveBack}}' class="floatL"></view>
<image bindtap="_goHome" src="/img/navbar_home_white.png"></image>
</view>
</view>
<!-- 手寫loading -->
<view class="navbar-loading" style='height:{{navbarHeight}}px;line-height:{{navbarHeight}}px;'>
<text>...</text>
</view>
為了適配不同手機屏幕, 高度和膠囊按鈕的位置都需要在html里面賦值 ,下面會詳細的說明高度如何計算。在自定義導(dǎo)航欄組件中分為兩部分, 一個是頂部的導(dǎo)航欄另一個是自己寫的loading。
因為自定義導(dǎo)航欄是fixed到頂部的, 為了保證不擋住下面的主體內(nèi)容,我們需要在導(dǎo)航欄和主體內(nèi)容之間添加一個跟導(dǎo)航欄相同的高度 ,class先叫做box。這樣可以保證導(dǎo)航欄不擋著主體內(nèi)容。但是會出現(xiàn)另一個問題,如果此頁面支持下拉刷新, 那么導(dǎo)航欄會把小程序原生的loading樣式擋住,而在主體內(nèi)容的前面會出現(xiàn)一個空白的box,雖說不影響使用,但是在用戶看來會很奇怪,莫名其妙的多出來一塊,box只有在loading結(jié)束后才會上去 。所以在這里需要自己手寫一個loading的動畫效果放在組件的最底下,高度跟導(dǎo)航欄一樣。
可以看到下面的最終效果,藍色導(dǎo)航條下面的三個點是小程序原生loading,再下面三個小點是自己寫的loading。
而我們想要的效果則是,當(dāng)小程序原生的loading被當(dāng)時,自己寫的loading就可以替代原生的loading
headerNavbar.js
狀態(tài)欄高度 = app.globalData.systeminfo.statusBarHeight
需要注意 膠囊位置信息的原點是在頁面的左上角 ,所以需要轉(zhuǎn)換一下,把 原膠囊位置信息起名為膠囊,轉(zhuǎn)換后的叫做現(xiàn)膠囊。
/*** iphone6 的膠囊位置信息
* wx.getMenuButtonBoundingClientRect() 坐標(biāo)信息以屏幕左上角為原點
* 膠囊寬度: 87
* 膠囊高度: 32
* 膠囊左邊界坐標(biāo): 278
* 膠囊上邊界坐標(biāo): 26
* 膠囊右邊界坐標(biāo): 365
* 膠囊下邊界坐標(biāo): 58
* 狀態(tài)欄高度:20*/
現(xiàn)膠囊上邊距 = 膠囊上邊界坐標(biāo) - 狀態(tài)欄高度
現(xiàn)膠囊右邊距 = 屏幕寬度 - 膠囊右邊界坐標(biāo)
現(xiàn)膠囊下邊距 = 膠囊下邊界坐標(biāo) - 膠囊高度 - 狀態(tài)欄高度
導(dǎo)航欄高度 = 膠囊下邊界坐標(biāo) + 現(xiàn)膠囊下邊距
注意:膠囊下邊界坐標(biāo)包含了 狀態(tài)欄、膠囊高度和狀態(tài)欄和膠囊高度之間的距離,因為膠囊是居中在導(dǎo)航欄里的 ,所以上邊距與下邊距應(yīng)該一致,所以是 膠囊下邊界坐標(biāo) - 膠囊高度 - 狀態(tài)欄高度。
const app = getApp();
Component({
properties: {
navbarData: { // 由父頁面?zhèn)鬟f的數(shù)據(jù)
type: Object,
value: {},
observer: function (newVal, oldVal) { }
}
},
data: {
haveBack: true, // 是否有返回按鈕,true 有 false 沒有 若從分享頁進入則為 false
statusBarHeight: 0, // 狀態(tài)欄高度
navbarHeight: 0, // 頂部導(dǎo)航欄高度
navbarBtn: { // 膠囊位置信息
height: 0,
width: 0,
top: 0,
bottom: 0,
right: 0
}
},
// 微信7.0.0支持wx.getMenuButtonBoundingClientRect()獲得膠囊按鈕高度
attached: function () {
let statusBarHeight = app.globalData.systeminfo.statusBarHeight // 狀態(tài)欄高度
let headerPosi = app.globalData.headerBtnPosi // 膠囊位置信息
/**
* wx.getMenuButtonBoundingClientRect() 坐標(biāo)信息以屏幕左上角為原點
* 菜單按鍵寬度: 87
* 菜單按鍵高度: 32
* 菜單按鍵左邊界坐標(biāo): 278
* 菜單按鍵上邊界坐標(biāo): 26
* 菜單按鍵右邊界坐標(biāo): 365
* 菜單按鍵下邊界坐標(biāo): 58
*/
let btnPosi = { // 膠囊實際位置,坐標(biāo)信息不是左上角原點
height: headerPosi.height,
width: headerPosi.width,
// 膠囊top - 狀態(tài)欄高度
top: headerPosi.top - statusBarHeight,
// 膠囊bottom - 膠囊height - 狀態(tài)欄height (現(xiàn)膠囊bottom 為距離導(dǎo)航欄底部的長度)
bottom: headerPosi.bottom - headerPosi.height - statusBarHeight,
// 屏幕寬度 - 膠囊right
right: app.globalData.systeminfo.screenWidth - headerPosi.right
}
let haveBack;
if (getCurrentPages().length === 1) { // 當(dāng)只有一個頁面時
haveBack = false;
} else {
haveBack = true;
}
this.setData({
haveBack: haveBack, // 獲取是否是通過分享進入的小程序
statusBarHeight: statusBarHeight,
navbarHeight: headerPosi.bottom + btnPosi.bottom, // 原膠囊bottom + 現(xiàn)膠囊bottom
navbarBtn: btnPosi
})
},
methods: {
_goBack: function () {
wx.navigateBack({
delta: 1
});
},
_goHome: function () {
wx.switchTab({
url: '/pages/index/index',
});
}
}
})
通過 getCurrentPages() 來判斷當(dāng)前頁面是否從分享頁進入, 因為如果從分享頁進入頁面棧中應(yīng)該只有一條數(shù)據(jù),在跳轉(zhuǎn)到其他頁面時頁面棧的length則會增加 ,在其他頁面就會顯示出返回和首頁按鈕。
注意:微信7.0.0支持wx.getMenuButtonBoundingClientRect(),如果想兼容低版本的微信,只能把導(dǎo)航欄的高度寫死,通過一些大佬的計算得出的高度:
'iPhone': 64,
'iPhone X': 88,
'android': 68
具體查看:
https://developers.weixin.qq.com/community/develop/doc/0006c012dc8028f04b070dd0551004
如果你使用 wx.getMenuButtonBoundingClientRect()得到信息有小數(shù) ,如下所示
{height: 24, width: 65.25, top: -0.5, bottom: -0.5, right: 101.25}
那么你可能是把開發(fā)工具中的視圖縮放了,還原成100%就正常了。
headerNavbar.wxss
.navbar-wrap {
position: fixed;
width: 100%;
top: 0;
z-index: 9999999;
background-color: #3281FF;
box-sizing: border-box;
}
.navbar-text {
text-align: center;
font-size: 36rpx;
color: #fff;
font-weight: 600;
}
.navbar-icon {
position: fixed;
display: flex;
border-radius: 64rpx;
border: 0.5px solid rgba(255,255,255, 0.3);
box-sizing: border-box;
}
.navbar-icon image {
height: 20px;
width: 20px;
padding: 5px 10px 10px;
display: inline-block;
overflow: hidden;
}
.navbar-icon view {
height: 18px;
border-left: 0.5px solid rgba(255,255,255, 0.3);
margin-top: 6px;
}
.navbar-loading {
background: #fff;
text-align: center;
}
引用組件頁面代碼
navigationStyle.json
{
"navigationStyle": "custom",
"enablePullDownRefresh": true,
"backgroundTextStyle": "light",
"usingComponents": {
"headerNavbar": "/components/headerNavbar/headerNavbar"
}
}
先在需要使用自定義導(dǎo)航欄的頁面json中添加navigationStyle:custom
enablePullDownRefresh: true 開啟下拉刷新
backgroundTextStyle: light是把loading的樣式改成白色,這樣就不會顯示出來loading的三個點
navigationStyle.wxml
<headernavbar navbar-data="{{nvabarData}}"></headernavbar>
<view class="home-page">
<text>
上面是自定義導(dǎo)航欄↑↑↑
</text>
<text>
下面是主體內(nèi)容↓↓↓
</text>
<navigator url="./testPage">
跳轉(zhuǎn)到測試頁
</navigator>
</view>
navigationStyle.js
Page({
data: {
// 組件所需的參數(shù)
nvabarData: {
showCapsule: 1,
// 是否顯示左上角膠囊按鈕 1 顯示 0 不顯示
title: '組件列表' // 導(dǎo)航欄 中間的標(biāo)題
}
},
onPullDownRefresh() {
setTimeout(() = >{
wx.stopPullDownRefresh(); // 停止下拉
},
2000);
},
})
注意:雖說這么做在小程序開發(fā)工具中看起來都是對的,得到的導(dǎo)航欄高度也是64px但是在真機上測試后,還是有偏差,在iphone8 plus上高度是60px。

可以通過這張圖明顯看到差了幾px,如果你是單獨幾個頁面使用自定義導(dǎo)航,細心的用戶可能會發(fā)現(xiàn),但是基本不影響。如果是全局使用自定義導(dǎo)航,那就不存在這個問題了。
項目代碼:https://github.com/Shay0921/header-navbar.git
總結(jié)
以上所述是小編給大家介紹的詳解微信小程序膠囊按鈕返回|首頁自定義導(dǎo)航欄功能,希望對大家有所幫助,如果大家有任何疑問歡迎給我留言,小編會及時回復(fù)大家的!
- 微信小程序?qū)崿F(xiàn)可拖動懸浮圖標(biāo)(包括按鈕角標(biāo)的實現(xiàn))
- 微信小程序?qū)㈨撁姘粹o懸浮固定在底部的實現(xiàn)代碼
- 微信小程序點擊按鈕動態(tài)切換input的disabled禁用/啟用狀態(tài)功能
- 微信小程序中的video視頻實現(xiàn) 自定義播放按鈕、封面圖、視頻封面上文案
- 微信小程序?qū)崿F(xiàn)單個卡片左滑顯示按鈕并防止上下滑動干擾功能
- 微信小程序批量監(jiān)聽輸入框?qū)Π粹o樣式進行控制的實現(xiàn)代碼
- 微信小程序 多行文本顯示...+顯示更多按鈕和收起更多按鈕功能
- 微信小程序按鈕點擊動畫效果的實現(xiàn)
- 操作按鈕懸浮固定在微信小程序底部的實現(xiàn)代碼
- 微信小程序mpvue點擊按鈕獲取button值的方法
- 微信小程序單選radio及多選checkbox按鈕用法示例
- 微信小程序開發(fā)之點擊按鈕退出小程序的實現(xiàn)方法
- 微信小程序按鈕巧妙用法
相關(guān)文章
js中數(shù)組解構(gòu)與對象解構(gòu)示例代碼
數(shù)組解構(gòu)是一種在 JavaScript 中從數(shù)組中提取值并將它們分配給變量的方式,在數(shù)組解構(gòu)中分為完全解構(gòu),不完全解構(gòu),解構(gòu)失敗以及解構(gòu)默認值,這篇文章主要介紹了js中數(shù)組解構(gòu)與對象解構(gòu),需要的朋友可以參考下2023-09-09
kindeditor修復(fù)會替換script內(nèi)容的問題
這里給大家分享的是個人修改的kindeditor的代碼,主要是修復(fù)了一些BUG,添加了些常用功能,推薦給大家,有需要的小伙伴可以參考下。2015-04-04

