RN-SafeAreaView
yaofly2012 opened this issue · comments
SafeAreaView
组件
功能
在设备安全区域内容展示页面内容:
原理
本质是个View
组件,但会自动添加padding
。
SafeAreaView
不是无脑的添加padding
,而是在适当的时候添加padding
:
- 上边缘触摸了设备顶部,即
坐标Y === 0
; - 左边缘触摸了设备左部,即
坐标X === 0
; - 下边缘超过设备底部,即
坐标Y + View高度 >= 设备高度
; - 右边缘超过设备右部,即
坐标X + View宽度 >= 设备宽度
;
当SafeAreaView
四边处于以上4中情况时,则会给边缘添加合适的padding
。
具体实现可以参考react-native-safe-area-view
库_getSafeAreaStyle
方法的实现。
// 检查`SafeAreaView`边缘是否触碰到设备边缘
_updateMeasurements = () => {
if (!this._isMounted) return;
if (!this._view.current) return;
const { width: WIDTH, height: HEIGHT } = getResolvedDimensions();
// calling getNode on the ref is no longer necessary in the future
const view = this._view.current.measureInWindow
? this._view.current
: this._view.current.getNode();
view.measureInWindow((realX, realY, winWidth, winHeight) => {
if (!this._view.current) {
return;
}
if (realY >= HEIGHT) {
realY = realY % HEIGHT;
} else if (realY < 0) {
realY = (realY % HEIGHT) + HEIGHT;
}
if (realX >= WIDTH) {
realX = realX % WIDTH;
} else if (realX < 0) {
realX = (realX % WIDTH) + WIDTH;
}
let nextState = {
touchesTop: realY === 0,
touchesBottom: realY + winHeight >= HEIGHT,
touchesLeft: realX === 0,
touchesRight: realX + winWidth >= WIDTH,
viewWidth: winWidth,
viewHeight: winHeight,
};
if (!shallowEquals(nextState, this.state)) {
this.setState(nextState);
}
});
};
使用
包裹整个页面组件
如果只是简单的把页面内容展示安全区域内,可以用SafeAreaView
+flex: 1
包裹页面组件即可。正如RN官方的[DEMO]:(https://reactnative.dev/docs/safeareaview#example):
import React from 'react';
import {StyleSheet, Text, SafeAreaView} from 'react-native';
const App = () => {
return (
<SafeAreaView style={styles.container}>
<Text style={styles.text}>Page content</Text>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
text: {
fontSize: 25,
fontWeight: '500',
},
});
export default App;
头部组件
为了实现更好的沉浸式头部组件(Header, Tab等)可以在这些组件内部使用SafeAreaView
。
底部组件
跟头部组件类似,还有些页面底部的组件中可以直接使用SafeAreaView
。
Issues/Concern
- 不能给
SafeAreaView
显示的指定padding
相关属性。 - 在
ScrollView
内部使用SafeAreaView
时会发生页面抖动。解决方案:contentInsetAdjustmentBehavior="automatic"