最近写小程序的时候,遇到了 iPhoneX底部小黑条与页面内容重叠的问题,其实就是iPhoneX底部安全区域的适配问题,总结一下适配iPhoneX及以上机型的底部安全区域适配方案。
前言
在苹果 iPhoneX 、iPhone XR及以上设备上,底部的物理Home键被取消,改为底部小黑条替代home键功能。微信小程序需要针对这种情况进行适配,否则可能会遇到底部按钮或选项卡栏与底部小黑条重叠的情况,如下图。
安全区域是什么意思 ?
想要解决内容与小黑条重叠的问题,我们需要先了解清楚苹果对于安全区域的定义。
安全区域指的是一个可视窗口范围,处于安全区域的内容不受圆角(corners)、齐刘海(sensor housing)、小黑条(Home Indicator)的影响。
下图是苹果官方给的图,另外 安全区域是在IOS11并且是iPhoneX及以上机型才有的,所以只需要适配这类机型。
这里我就给大家介绍一下比较常用的两种适配方案。
方案一:使用微信官方API,getSystemInfoSync函数进行适配
通过该API可以获取到屏幕的高度
还有竖屏正方向下的安全区域 safeArea对象的bottom属性
1. 为了方便使用我们需要创建一个全局存储高度的属性:bottomHeight
// 数据都是根据当前机型进行计算,这样的方式兼容大部分机器,导航栏、胶囊获取可无视,需要自取
globalData: {
// navBarHeight: 0, // 导航栏高度
// menuRight: 0, // 胶囊距右方间距(方保持左、右间距一致)
// menuTop: 0, // 胶囊距顶部间距
// menuHeight: 0, // 胶囊高度(自定义内容可与胶囊高度保证一致)
bottomHeight: 0 // 底部安全区域高度
},
2. 在App.vue 的 onLaunch函数中添加以下代码获取值
onLaunch: function () {
const that = this
// 获取系统信息
const systemInfo = uni.getSystemInfoSync()
that.globalData.bottomHeight = systemInfo.screenHeight - systemInfo.safeArea.bottom
// 胶囊按钮位置信息
// const menuButtonInfo = uni.getMenuButtonBoundingClientRect()
// 导航栏高度 = 状态栏高度 + 44
// that.globalData.navBarHeight = systemInfo.statusBarHeight + systemInfo.safeArea.top
// that.globalData.menuRight = systemInfo.screenWidth - menuButtonInfo.right
// that.globalData.menuTop = menuButtonInfo.top;
// that.globalData.menuHeight = menuButtonInfo.height;
// getSystemInfo函数同样可以拿到,这个是 异步获取系统信息
uni.getSystemInfo({
success: (res) => {
console.log(res);
that.globalData.bottomHeight = res.screenHeight - res.safeArea.bottom
}
})
}
3. 在需要兼容底部安全区域的 vue文件中的onLoad函数中获取设置的全局变量安全区域高度 bottomHeight
onLoad() {
// 注意需要使用getApp()去获取全局变量
this.bottomHeight = getApp().globalData.bottomHeight
},
4. 最后在所需页面的结构里添加以下代码就完成了苹果的底部安全区域适配
<view class="container" :style="{ paddingBottom: bottomHeight + 'px' }"></view>
方案二:使用苹果官方推出的适配方案css函数env()、constant()来适配
苹果官方推荐使用env(),constant()来适配,建议使用该方案,不需要管数值具体是多少。
env()和constant(),是IOS11新增特性,Webkit的css函数,用于设定安全区域与边界的距离,有4个预定义变量:
safe-area-inset-left:安全区域距离左边边界的距离
safe-area-inset-right:安全区域距离右边边界的距离
safe-area-inset-top:安全区域距离顶部边界的距离
safe-area-inset-bottom :安全距离底部边界的距离
注意:env()和constant()函数有个必要的使用前提,当网页设置viewport-fit=cover的时候才生效,根据微信小程序的表现和我在实际真机测试时这两个函数生效,推测小程序里的viewport-fit默认是cover。
还有一点,在IOS11.2系统以前,可以使用constant()函数,但是在IOS11.2系统以后,这个函数就被废弃了,被env()函数替代了。
所以我们在做屏幕适配时,需要这样写:
// 写在需要添加底部边距的盒子上
padding-bottom: constant(safe-area-inset-bottom); /*兼容 IOS<11.2*/
padding-bottom: env(safe-area-inset-bottom); /*兼容 IOS>11.2*/
如果我们需要额外的距离也可以使用calc函数来写:
padding-bottom: calc(constant(safe-area-inset-bottom) + 50rpx); /*兼容 IOS<11.2*/
padding-bottom: clac(env(safe-area-inset-bottom) + 50rpx); /*兼容 IOS>11.2*/
// 就是在适配底部小黑条的基础上又增加了50rpx的底部内边距
适配后的页面: