注册

优雅解决uniapp微信小程序右上角胶囊菜单覆盖问题

前言


大家好,今天聊一下在做uniapp多端适配项目,需要用到自定义导航时,如何解决状态栏塌陷及导航栏安全区域多端适配问题,下文只针对H5、APP、微信小程序三端进行适配,通过封装一个通用高阶组件包裹自定义导航栏内容,主要是通过设置padding来使内容始终保持在安全区域,达到低耦合,可复用性强的效果。


一、创建NavbarWrapper.vue组件


大致结构如下:




<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变量的介绍:


image.png


从上图可以知道--status-bar-height只在APP端是手机实际状态栏高度,在微信小程序是固定的25px,并不是手机实际状态栏高度;


微信小程序时,除了状态栏高度还需要获取右上角的胶囊菜单所占宽度,保持导航栏在安全区域。


以下使用uni.getWindowInfo()uni.getMenuButtonBoundingClientRect()来分别获取状态栏高度和胶囊相关信息,api介绍如下图所示:


image.png


image.png


主要逻辑代码


在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">headerview>
NavbarWrapper>

二、多端效果展示


微信小程序


b15a0866000c13e58259645f2459440.jpg


APP端


45ee33b12dcf082e5ac76dc12fc41de.jpg


H5端


22b1984f8b21a4cb79f30286a1e4161.jpg


三、源码


NavbarWrapper.vue




<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>




作者:vilan_微澜
来源:juejin.cn/post/7309361597556719679

0 个评论

要回复文章请先登录注册