关于字节跳动小程序不支持env(safe-area-inset-bottom)的解决方案
因为我们的项目是用Taro写的,所以下面的代码是用tsx代码,如果是头条原生代码编写,改一改就行,原理一致
经过前期的一些尝试和调研发现:字节小程序它不是不支持env(safe-area-inset-bottom)
,而是使用这个属性得到的值是0
。 使用 tt.getSystemInfoSync
可以获取到设备的上下的安全距离(safeArea
)。
我们不妨想这么一个思路。
-
全局定义一个CSS变量,默认值设置为
env(safe-area-inset-bottom)
(方便未来某一天小程序支持了这个属性我们去除) -
定义一个
Wrapper
组件去包装一下页面组件(也可以不定义wrapper组件,我这里定定义是为了抹平多端小程序,也为了方便以后去除。)- 使用
tt.getSystemInfoSync
获取到设备的上下的安全距离(safeArea
)
底部安全距离计算公式: safeAreaBottomHeight = safeArea.bottom - safeArea.height
- 将底部安全距离的数值赋值给刚才全局定义的css变量
- 使用
-
至此,所有CSS中需要用到
env(safe-area-inset-bottom)
的地方使用var(全局css变量)
即可。如:padding-bottom: var(--safe-area)
所有用到这个变量的页面都需要使用
Wrapper
组件包装一下
定义全局CSS变量
// app.scss
:global {
--safe-area: env(safe-area-inset-bottom);
}
创建Wrapper组件并在内部修改CSS变量的值
// Wrapper.tsx
import React from 'react'
import { View } from '@tarojs/components'
import { getSystemInfoByKey } from '@src/utils/native/device'
function getSystemInfoByKey<TKey extends keyof DeviceProps>(key: TKey) {
const props = Taro.getSystemInfo()
return props[key]
}
const safeAreaInfo = getSystemInfoByKey('safeArea')
export default function Index(props: { children: React.ReactNode }) {
const safeAreaHeight = `${safeAreaInfo.bottom - safeAreaInfo.height}px`
return (
<View style={
{
// @ts-ignore
'--safe-area': safeAreaHeight,
}
}
>
{props.children}
</View>
)
}
使用Wrapper组件
import React from 'react'
import Wrapper from './components/Wrapper' // Wrapper组件
import Page from '../Index' // 页面组件
export default () => (
<Wrapper>
<Page />
</Wrapper>
)
使用CSS变量
这里只是举例说明,根据你的需求使用即可。
实现一个设置底部安全区域的 SCSS
方法
@mixin safeAreaPaddingBottom($paddingBottom: 0px) {
@if $paddingBottom==0px {
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: var(--safe-area);
}
@else {
padding-bottom: calc(#{$paddingBottom} + constant(safe-area-inset-bottom));
padding-bottom: calc(#{$paddingBottom} + var(--safe-area));
}
}
.box {
@include safeAreaPaddingBottom()
}