Hiding the Native NavigationBar
To customize the navigation bar, first hide the native one. There are two approaches:
-
Global Customization
In the global configuration (e.g.,manifest.json), setnavigationStyletocustom:"globalStyle": { "navigationStyle": "custom" } -
Page-Specific Customization
For individual pages, configure in the page’sstyleproperty:{ "pages": [ { "path": "pages/index/index", "style": { "navigationStyle": "custom" // Enable custom navigation for this page } } // Other pages... ] }
Encapsulating a Custom Navigation Bar Component
After setting navigationStyle to custom, the page’s top navigation must be built manually. Key challenges:
- What is the correct height for the navigation bar?
- How to avoid overlap with device notches or status icons?
Different phone models have varying navigation bar heights. To adapt to more devices, calculate the height dynamical:
- Status Bar Height: Obtained via
uni.getSystemInfo(). - Capsule Button Info: Obtained via
wx.getMenuButtonBoundingClientRect()(native component, units inpx).
The formula for the navigation bar height:
navHeight = statusBarHeight + capsuleHeight + 2 * (capsuleTop - statusBarHeight)
(Where capsuleTop is the capsule’s top distance from the screen, and statusBarHeight is the status bar height.)
Implemantation Steps
1. Create a Custom Navigation Component (CustomNavbar)
Vue Tmeplate
<view class="custom-navbar" :style="{'background': bgColor, 'height': navHeight + 'px'}">
<view :style="{'height': capsuleH + 'px', 'top': capsuleT + 'px'}" class="back-area">
<view class="back-arrow" v-if="showBack" @click="goBack"></view>
</view>
<view class="title-text" :style="{ 'height': capsuleH + 'px', 'top': capsuleT + 'px' }">
{{ pageTitle }}
</view>
</view>
CSS Styles
.custom-navbar {
width: 100%;
position: fixed;
top: 0;
z-index: 99;
}
.back-area {
position: absolute;
left: 40rpx;
z-index: 999;
display: flex;
align-items: center;
}
.back-arrow {
width: 20rpx;
height: 20rpx;
border: 5rpx solid #FFFFFF;
border-right-color: transparent;
border-bottom-color: transparent;
transform: rotate(-45deg);
}
.title-text {
position: absolute;
left: 0;
right: 0;
font-size: 28rpx;
color: #FFFFFF;
display: flex;
align-items: center;
justify-content: center;
}
JavaScript Logic
export default {
props: {
pageTitle: {
type: String,
default: 'Home'
},
bgColor: {
type: String,
default: 'linear-gradient(to right, #FF3413, #FF924D)'
},
showBack: {
type: Boolean,
default: true
}
},
data() {
return {
capsuleT: '', // Distance from capsule to top
capsuleH: '', // Capsule height
navHeight: '' // Navigation bar height
}
},
onLoad() {
const app = getApp();
this.capsuleT = app.globalData.menuButton.top;
this.capsuleH = app.globalData.menuButton.height;
const statusBarH = app.globalData.system.statusBarHeight;
this.navHeight = (this.capsuleT - statusBarH) * 2 + this.capsuleH + statusBarH;
},
methods: {
goBack() {
uni.navigateBack({ delta: 1 });
}
}
}
2. Global Initialization in app.vue
In app.vue, fetch system and capsule button info once:
export default {
globalData: {
system: {},
menuButton: {}
},
onLaunch() {
// Fetch system info
uni.getSystemInfo({
success: (res) => {
this.globalData.system = res;
}
});
// Fetch capsule button info
this.globalData.menuButton = wx.getMenuButtonBoundingClientRect();
}
}
3. Using the Component
Import and use the CustomNavbar component in any page requiring a custom navigation bar.