UniApp微信小程序自定義導航欄
在UniApp開發微信小程序時,頁面左上角默認有一個返回按鈕(在導航欄左側),但有時我們需要自定義這個按鈕的樣式和功能,同時保持與導航欄中間的標題和右側膠囊按鈕(藥丸屏)的高度一致。
微信小程序的導航欄分為三部分:左側(返回和主頁)、中間(標題)、右側(膠囊按鈕)。自定義左側按鈕時,我們需要注意以下幾點:
-
微信小程序的導航欄是原生的,我們無法直接修改原生返回按鈕的樣式,因此常見的做法是隱藏原生導航欄,使用自定義導航欄。
-
自定義導航欄需要計算導航欄的高度,尤其是要考慮到不同機型的適配(如iPhone的劉海屏、狀態欄高度等)。
-
右側的膠囊按鈕(藥丸屏)的尺寸和位置是固定的,我們可以通過微信提供的API獲取其位置信息,以便讓自定義按鈕與膠囊按鈕對齊。
具體步驟如下:
1. 隱藏原生導航欄
在pages.json
中,設置頁面或全局的導航欄為自定義:
{"pages": [{"path": "pages/index/index","style": {"navigationStyle": "custom" // 使用自定義導航欄}}],// 或者全局設置"globalStyle": {"navigationStyle": "custom"}}
2. 在頁面中編寫自定義導航欄
在頁面的vue文件中,我們需要自己編寫一個導航欄組件,通常放在頁面頂部。
3. 獲取狀態欄高度和膠囊按鈕位置
我們可以使用uni.getSystemInfoSync()
來獲取狀態欄高度,以及使用uni.getMenuButtonBoundingClientRect()
來獲取膠囊按鈕的位置信息。
示例代碼:
const systemInfo = uni.getSystemInfoSync();const menuButtonInfo = uni.getMenuButtonBoundingClientRect();// 狀態欄高度(手機頂部狀態欄區域的高度)const statusBarHeight = systemInfo.statusBarHeight;// 膠囊按鈕距離頂部的距離(通常比狀態欄高度多一點點,具體以獲取到的為準)const menuButtonTop = menuButtonInfo.top;// 導航欄高度 = 膠囊按鈕高度 + (膠囊按鈕上邊距 - 狀態欄高度) * 2// 因為膠囊按鈕上下有間隙,所以導航欄高度可以這樣計算:const navBarHeight = (menuButtonTop - statusBarHeight) * 2 + menuButtonInfo.height;// 整個自定義導航欄的高度 = 狀態欄高度 + 導航欄高度const customBarHeight = statusBarHeight + navBarHeight;
4. 布局自定義導航欄
在模板中,我們使用計算得到的高度來設置導航欄的樣式,確保高度與原生導航欄一致。
左側按鈕的位置需要與膠囊按鈕對齊(垂直方向),因此我們可以將左側按鈕的頂部設置為menuButtonTop
(膠囊按鈕的頂部位置),然后通過調整上邊距或使用絕對定位來實現。
示例模板結構:
<template><view><!-- 自定義導航欄 --><view class="custom-nav" :style="{ height: customBarHeight + 'px', paddingTop: statusBarHeight + 'px' }"><!-- 左側按鈕 --><view class="left-btn" :style="{ top: menuButtonTop + 'px' }" @click="goHome"><!-- 這里可以放置自定義圖標或文字 --><image src="/static/home.png" mode="aspectFit"></image></view><!-- 中間標題 --><view class="title" :style="{ height: navBarHeight + 'px', lineHeight: navBarHeight + 'px' }">標題</view><!-- 右側通常不需要添加內容,因為膠囊按鈕是原生的,但我們也可以自定義右側內容,但要注意與膠囊按鈕的位置不重疊 --></view><!-- 頁面內容,需要設置一個上邊距,避免被導航欄覆蓋 --><view :style="{ marginTop: customBarHeight + 'px' }">... 頁面內容 ...</view></view></template>
樣式示例(使用scss):
.custom-nav {position: fixed;top: 0;left: 0;width: 100%;box-sizing: border-box;background-color: #ffffff;z-index: 999;.left-btn {position: absolute;left: 10px;height: 30px; // 膠囊按鈕的高度可以通過menuButtonInfo.height獲取,這里假設30pxdisplay: flex;align-items: center;justify-content: center;// 通過top定位垂直位置,與膠囊按鈕對齊image {width: 20px;height: 20px;}}.title {text-align: center;font-size: 16px;}}
5. 自定義按鈕的功能
在goHome
方法中,我們可以實現跳轉到首頁的功能:
methods: {goHome() {uni.reLaunch({url: '/pages/index/index'});}}
注意事項:
-
由于自定義導航欄是固定在頂部的,頁面內容需要設置一個上邊距(等于自定義導航欄的高度),避免內容被導航欄覆蓋。
-
不同機型的膠囊按鈕位置可能略有差異,所以一定要動態獲取膠囊按鈕的位置信息。
-
在微信開發者工具中,膠囊按鈕的位置信息可能與真機有差異,建議在真機測試。
通過以上步驟,我們就可以自定義一個與中間標題和右側膠囊按鈕高度一致的左側按鈕,并實現自定義功能。
在 UniApp 開發微信小程序時,要自定義左上角返回按鈕并保持與標題欄、右側膠囊按鈕高度對齊,需使用自定義導航欄方案。以下是完整實現步驟:
核心思路
隱藏原生導航欄,使用自定義導航欄組件
精確計算布局尺寸,匹配微信膠囊按鈕位置
使用絕對定位控制自定義按鈕位置
實現步驟
1. 配置全局自定義導航欄(pages.json)
{"globalStyle": {"navigationStyle": "custom","transparentTitle": "always","navigationBarTextStyle": "black"}
}
2. 創建自定義導航欄組件(components/custom-navbar.vue)
<template><view class="custom-navbar"><!-- 狀態欄占位 --><view :style="{ height: statusBarHeight + 'px' }"></view><!-- 導航欄主體 --><view class="navbar-content" :style="{ height: navBarHeight + 'px' }"><!-- 左側自定義按鈕 --><view class="custom-home-btn" :style="btnStyle"@click="handleHomeClick"><image src="/static/home-icon.png" class="icon" /></view><!-- 標題居中 --><view class="title" :style="titleStyle">{{ title }}</view></view></view>
</template><script>
export default {props: {title: String},data() {return {statusBarHeight: 20, // 默認值navBarHeight: 44, // 默認值menuButtonInfo: null};},computed: {// 按鈕樣式計算(核心)btnStyle() {if (!this.menuButtonInfo) return {};return {width: '30px',height: this.menuButtonInfo.height + 'px',top: this.menuButtonInfo.top + 'px'};},// 標題位置適配titleStyle() {return {height: this.menuButtonInfo.height + 'px',lineHeight: this.menuButtonInfo.height + 'px'};}},mounted() {this.initSystemInfo();},methods: {initSystemInfo() {const systemInfo = uni.getSystemInfoSync();this.statusBarHeight = systemInfo.statusBarHeight;// 獲取微信膠囊按鈕位置const menuButtonInfo = uni.getMenuButtonBoundingClientRect();this.menuButtonInfo = menuButtonInfo;// 計算導航欄高度 = 膠囊按鈕高度 + (膠囊按鈕上間距 - 狀態欄高度) * 2this.navBarHeight = menuButtonInfo.height + (menuButtonInfo.top - systemInfo.statusBarHeight) * 2;},handleHomeClick() {// 自定義按鈕功能(示例:返回首頁)uni.reLaunch({ url: '/pages/index/index' });}}
};
</script><style scoped>
.custom-navbar {position: fixed;top: 0;left: 0;right: 0;z-index: 9999;background: white;
}.navbar-content {position: relative;display: flex;justify-content: center;align-items: center;
}.custom-home-btn {position: absolute;left: 15px;display: flex;align-items: center;justify-content: center;z-index: 10;
}.icon {width: 22px;height: 22px;
}.title {font-size: 16px;font-weight: 500;max-width: 60%;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;
}
</style>
3. 在頁面中使用自定義導航欄
<template><view><!-- 引入自定義導航欄 --><custom-navbar title="我的頁面" /><!-- 頁面內容 (需要設置頂部內邊距) --><view :style="{ paddingTop: navBarTotalHeight + 'px' }"><!-- 頁面內容... --></view></view>
</template><script>
import customNavbar from '@/components/custom-navbar.vue'export default {components: { customNavbar },data() {return {// 計算:狀態欄高度 + 導航欄高度navBarTotalHeight: 64 // 默認值}},onLoad() {this.calcNavbarHeight()},methods: {calcNavbarHeight() {const systemInfo = uni.getSystemInfoSync()const menuButtonInfo = uni.getMenuButtonBoundingClientRect()this.navBarTotalHeight = systemInfo.statusBarHeight + menuButtonInfo.height + (menuButtonInfo.top - systemInfo.statusBarHeight) * 2}}
}
</script>
關鍵點說明
膠囊按鈕對齊原理:
- 使用 uni.getMenuButtonBoundingClientRect() 獲取膠囊按鈕的精確位置信息
- 通過公式計算導航欄高度:膠囊高度 + (膠囊上間距 - 狀態欄高度) × 2
- 按鈕垂直定位使用膠囊按鈕的 top 值
響應式處理:
- 不同機型適配(iPhone 劉海屏、Android 等)
- 小程序右上角膠囊按鈕位置是固定的
- 頁面滾動時導航欄保持固定定位
樣式定制:
- 替換 /static/home-icon.png 為自定義圖標
- 調整 left 值控制水平位置
- 修改按鈕的寬高和圖標尺寸
注意事項
- **真機測試:**微信開發者工具中的膠囊位置與真機可能有差異
- **iOS 安全區域:**iPhone X 及以上機型需要處理底部安全區域
- **頁面滾動:**頁面內容需要設置 padding-top 避免內容被導航欄遮擋
- **組件復用:**建議封裝成全局組件減少重復代碼
通過此方案,自定義按鈕可以實現:
- 與原生膠囊按鈕完美對齊 ?
- 支持自定義圖標和點擊事件 ?
- 完美適配不同機型 ?
- 保持原生導航欄流暢體驗 ?