RN - 适配安卓全面屏

ReactNative 中对安卓全面屏手机的进行适配,去除底边。

最近对 RN 项目打了包,在安卓端进行真机调试,各种水土不服。主要就是在全面屏下高度不匹配,底边会多出一段白边。下面简单解释一下原因,并给出解决方案:

高度获取

RN 中,我们一般通过以下代码获取设备高度,并将其设置为视口高度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import {Dimensions} from 'react-native';

export default class Example extends Component {
render() {
return (
<View style={styles.container}>
...
</View>
);
}
}

const styles = StyleSheet.create({
container: {
backgroundColor: '#f0f3f6',
height: Dimensions.get('window').height, //将设备高度设置为视口高度,少一截
},
});

在一般情况下这是设置是没有问题的,整个 视口高度 会以 设备高度 为准撑满整个屏幕。但是在 全面屏 或者使用 Navbar 的时候就会出问题了,需要进行适配。

全面屏

原因

市场上大多数的全面屏安卓手机,一般都是以 刘海屏水滴屏挖孔屏 等异形屏的形式存在。以 小米10(挖孔屏) 为例,屏幕在显示 UI 界面的时候,顶上的挖孔部分一般都是作为 状态栏 的形式存在。

Dimensions.get('window').height 在计算高度的时候不会将他计算进去。但是在实际渲染界面的时候,这部分又会被作为可视区域计算进去。这就造成了 Dimensions.get('window').height 获取的 设备高度设备实际高度 少了一截(状态栏),就会在底部就会以白条的形式进行补全,太丑了……

白边

解决方案

所以我们只要在 Dimensions.get('window').height 获取高度的时候,把状态栏的高度也给加上去,作为视口高度就可以了。获取状态栏高度的方法:StatusBar.currentHeight

改写上面栗子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import {Dimensions, StatusBar} from 'react-native';

export default class Example extends Component {
render() {
return (
<View style={styles.container}>
...
</View>
);
}
}

const styles = StyleSheet.create({
container: {
backgroundColor: '#f0f3f6',
height: Dimensions.get('window').height + StatusBar.currentHeight, //补上状态栏高度,刚刚好
},
});

那么如何保证不误伤 正常屏 呢?这里给出龙鸣方法:通过判断 纵横比。一般比值大于1.8的是全面屏,小于1.8的是正常屏,代码如下:

1
2
3
4
import {Dimensions, StatusBar} from 'react-native';
const {width, height} = Dimensions.get('window');
const wh = height / width;
const height = wh > 1.8 ? height + StatusBar.currentHeight : height;

完美

底部导航栏

原因

我们一般会在主屏使用 Navigation底部导航栏,这个导航栏也是有高度的,并且在 Dimensions.get('window').height 获取高度的时候导航栏的高度也会被计算进去。这就造成了一个问题:导航栏会遮挡页面上的组件。

解决方案

所以我们只要把导航栏的高度减去即可:Dimensions.get('window').height - 49

这边的 49 是我使用的导航栏的高度,一般导航栏高度都是固定的,我们只需要测量一下直接减去数值即可。

简单封装

若是每个页面都为了计算高度而写一堆花里胡哨的逻辑代码,也太扯淡了。还是需要简单封装一下,如下:

1
2
3
4
5
6
7
8
//height.js

import {Dimensions, StatusBar} from 'react-native';
const {width, height} = Dimensions.get('window');
const wh = height / width;
const realHeight = wh > 1.8 ? height + StatusBar.currentHeight + 46 : height; //不带导航栏的真实高度
const windowHeight = wh > 1.8 ? height + StatusBar.currentHeight : height - 49; //减去导航栏的视口高度
export {realHeight, windowHeight};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//page with tabbar

import {windowHeight} from 'height';

export default class Example extends Component {
render() {
return (
<View style={styles.container}>
...
</View>
);
}
}

const styles = StyleSheet.create({
container: {
height: windowHeight
},
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//page without tabbar

import {realHeight} from 'height';

export default class Example extends Component {
render() {
return (
<View style={styles.container}>
...
</View>
);
}
}

const styles = StyleSheet.create({
container: {
height: realHeight
},
});

最后吐槽一下!

把前置摄像头砍了!完完全全的全面屏!它不香么?!

后置摄像头那么多有什么用?!一颗大底高素质镜头足矣!

查看评论