這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 前言 大家好,今天聊一下在做uniapp多端適配項目,需要用到自定義導航時,如何解決狀態欄塌陷及導航欄安全區域多端適配問題,下文只針對H5、APP、微信小程式三端進行適配,通過封裝一個通用高階組件包裹自定義導航欄內容,主要是通過設置pad ...
這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助
前言
大家好,今天聊一下在做uniapp多端適配項目,需要用到自定義導航時,如何解決狀態欄塌陷及導航欄安全區域多端適配問題,下文只針對H5、APP、微信小程式三端進行適配,通過封裝一個通用高階組件包裹自定義導航欄內容,主要是通過設置padding來使內容始終保持在安全區域,達到低耦合,可復用性強的效果。
一、創建NavbarWrapper.vue組件
大致結構如下:
<template> <view class="navbar-wrapper" :style="{ paddingTop: statusBarHeight, paddingRight: rightSafeArea }"> <slot/> </view> </template> <script> export default { name: 'NavbarWrapper', data() { return { // 像素單位 pxUnit: 'px', // 預設狀態欄高度 statusBarHeight: 'var(--status-bar-height)', // 微信小程式右上角的膠囊菜單寬度 rightSafeArea: 0 } } } </script> <style scoped> .navbar-wrapper { /** * 元素的寬度和高度包括了內邊距(padding)和邊框(border), * 而不會被它們所占據的空間所影響 * 子元素繼承寬度時,只會繼承內容區域的寬度 */ box-sizing: border-box; } </style>
目的
主要是動態計算statusBarHeight和rightSafeArea的值。
解決方案
在APP端只需一行css代碼即可
.navbar-wrapper { padding-top: var(--status-bar-height); }
下麵是關於--status-bar-height
變數的介紹:
從上圖可以知道--status-bar-height
只在APP端是手機實際狀態欄高度,在微信小程式是固定的25px
,並不是手機實際狀態欄高度;
在微信小程式時,除了狀態欄高度還需要獲取右上角的膠囊菜單所占寬度,保持導航欄在安全區域。
以下使用uni.getWindowInfo()
和uni.getMenuButtonBoundingClientRect()
來分別獲取狀態欄高度和膠囊相關信息,api介紹如下圖所示:
主要邏輯代碼
在NavbarWrapper組件創建時,做相關計算
created() { const px = this.pxUnit // #ifndef H5 // 獲取視窗信息 const windowInfo = uni.getWindowInfo() this.statusBarHeight = windowInfo.statusBarHeight + px // #endif // #ifdef MP-WEIXIN // 獲取膠囊左邊界坐標 const { left } = uni.getMenuButtonBoundingClientRect() // 計算膠囊(包括右邊距)占據屏幕的總寬度:屏幕寬度-膠囊左邊界坐標 this.rightSafeArea = windowInfo.windowWidth - left + px // #endif }
用法
<NavbarWrapper> <view class="header">header</view> </NavbarWrapper>
二、多端效果展示
微信小程式
APP端
H5端
三、源碼
NavbarWrapper.vue
<template> <view class="navbar-wrapper" :style="{ paddingTop: statusBarHeight, paddingRight: rightSafeArea }"> <slot/> </view> </template> <script> export default { name: 'NavbarWrapper', data() { return { // 像素單位 pxUnit: 'px', // 預設狀態欄高度 statusBarHeight: 'var(--status-bar-height)', // 微信小程式右上角的膠囊菜單寬度 rightSafeArea: 0 } }, created() { const px = this.pxUnit // #ifndef H5 // 獲取視窗信息 const windowInfo = uni.getWindowInfo() this.statusBarHeight = windowInfo.statusBarHeight + px // #endif // #ifdef MP-WEIXIN // 獲取膠囊左邊界坐標 const { left } = uni.getMenuButtonBoundingClientRect() // 計算膠囊(包括右邊距)占據屏幕的總寬度:屏幕寬度-膠囊左邊界坐標 this.rightSafeArea = windowInfo.windowWidth - left + px // #endif } } </script> <style scoped> .navbar-wrapper { /** * 元素的寬度和高度包括了內邊距(padding)和邊框(border), * 而不會被它們所占據的空間所影響 * 子元素繼承寬度時,只會繼承內容區域的寬度 */ box-sizing: border-box; background-color: deeppink; } </style>