react-native-safe-area-context
一种灵活的处理安全区域的方式,在Android和Web上也适用!
入门指南
npm install react-native-safe-area-context
yarn add react-native-safe-area-context
然后你需要为你所使用的平台链接库的原生部分。
-
iOS 平台:
$ npx pod-install
支持的 react-native 版本
版本 | react-native 版本 |
---|---|
4.0.0+ | 0.64.0+ |
新架构支持
这个库目前对新的 react-native 架构有实验性支持。请注意,将会有重大变更,并且只支持最新版本的 react-native。
您需要使用 4.4.0 和 react-native 0.70+。
使用
这个库有两个重要的概念,如果你熟悉 React 上下文,这很类似。
提供者
SafeAreaProvider组件是一个 View
,其中由消费者提供的内边距是相对于该 view 的。这意味着,如果这个 view 与任何系统元素(状态栏、凹槽等)重叠,这些值将被提供给后代消费者。通常,您将在应用程序的顶部有一个提供者。
消费者
消费者是组件和钩子,允许使用最近的父Provider提供的内边距值。这些值总是相对于提供者,而不是这些组件。
-
SafeAreaView是首选的消费方式。这是一个带有应用内边距的常规
View
。它通过本地应用内边距获得更好的性能,并避免了使用其他基于 JS 的消费者可能出现的闪烁。 -
useSafeAreaInsets提供更多灵活性,但在某些情况下可能会导致一些布局闪烁。如果您需要更多地控制内边距的应用方式,请使用它。
API
SafeAreaProvider
您应该在应用程序的根组件中添加 SafeAreaProvider
。当使用 react-native-screens
时,您可能需要在其他地方添加它,如模态和路由的根部。
请注意,提供者不应该在用 Animated
动画的 View
内部或 ScrollView
内部,因为这可能导致非常频繁的更新。
示例
import { SafeAreaProvider } from 'react-native-safe-area-context';
function App() {
return <SafeAreaProvider>...</SafeAreaProvider>;
}
属性
接受所有 View属性。默认样式为 {flex: 1}
。
initialMetrics
可选的,默认为 null
。
可用于提供帧和内边距的初始值,这样可以立即渲染。有关如何使用此属性的更多信息,请参见优化。
SafeAreaView
SafeAreaView
是一个常规的 View
组件,其安全区域内边距被应用为填充或边距。
填充或边距样式会添加到内边距中,例如在具有 20 个内边距的 SafeAreaView
上设置 style={{paddingTop: 10}}
将导致顶部填充为 30。
示例
import { SafeAreaView } from 'react-native-safe-area-context';
function SomeComponent() {
return (
<SafeAreaView style={{ flex: 1, backgroundColor: 'red' }}>
<View style={{ flex: 1, backgroundColor: 'blue' }} />
</SafeAreaView>
);
}
属性
接受所有 View属性。
edges
可选的,top
、right
、bottom
和left
的数组。默认为全部。
设置应用安全区域内边距的边缘。
例如,如果您不想将内边距应用于顶部边缘,因为该视图不接触屏幕顶部,您可以使用:
<SafeAreaView edges={['right', 'bottom', 'left']} />
它还可以设置为一个对象 { top?: EdgeMode, right?: EdgeMode, bottom?: EdgeMode, left?: EdgeMode }
,其中 EdgeMode = 'off' | 'additive' | 'maximum'
。 Additive 是默认模式,和传递边缘数组是一样的: finalPadding = safeArea + padding
。最大模式将使用安全区域内边距或填充/边距(取决于 mode
)如果安全区域小于则: finalPadding = max(safeArea, padding)
。例如,如果您想要一个浮动的 UI 元素,应该位于底部安全区域边缘上的设备上,或者如果安全区域小于 24px 则位于屏幕底部 24px 处:
<SafeAreaView style={{paddingBottom: 24}} edges={{bottom: 'maximum'}} />
mode
可选的,'填充'(默认)或'边距'。
将安全区域应用于填充或边距。
这对于创建感知安全区域的分隔组件很有用,例如:
<SafeAreaView mode="margin" style={{ height: 1, backgroundColor: '#eee' }} />
useSafeAreaInsets
返回最近提供程序的安全区域内插值。这允许从JavaScript操纵插入值。请注意,插入值不会同步更新,因此在旋转屏幕时可能会导致轻微延迟。
对象包含 { top: number, right: number, bottom: number, left: number }
。
import { useSafeAreaInsets } from 'react-native-safe-area-context';
function HookComponent() {
const insets = useSafeAreaInsets();
return <View style={{ paddingBottom: Math.max(insets.bottom, 16) }} />;
}
useSafeAreaFrame
返回最近提供程序的框架。这可以作为 Dimensions
模块的替代方法使用。
对象包含 { x: number, y: number, width: number, height: number }
SafeAreaInsetsContext
具有安全区域内插值的React上下文。
可以与类组件一起使用:
import { SafeAreaInsetsContext } from 'react-native-safe-area-context';
class ClassComponent extends React.Component {
render() {
return (
<SafeAreaInsetsContext.Consumer>
{(insets) => <View style={{ paddingTop: insets.top }} />}
</SafeAreaInsetsContext.Consumer>
);
}
}
withSafeAreaInsets
高阶组件,提供安全区域内插值作为 insets
属性。
type Props = WithSafeAreaInsetsProps & {
someProp: number;
};
class ClassComponent extends React.Component<Props> {
render() {
return <View style={{ paddingTop: this.props.insets.top }} />;
}
}
const ClassComponentWithInsets = withSafeAreaInsets(ClassComponent);
<ClassComponentWithInsets someProp={1} />;
SafeAreaFrameContext
具有安全区域框架值的React上下文。
initialWindowMetrics
初始渲染时窗口的内插值和框架。这可以与 SafeAreaProvider
的 initialMetrics
一起使用。参见优化了解更多信息。
对象包含:
{
frame: { x: number, y: number, width: number, height: number },
insets: { top: number, left: number, right: number, bottom: number },
}
注意: 此值可能为空或过时,因为它是在创建本机模块时计算的。
已弃用的API
useSafeArea
使用 useSafeAreaInsets
代替。
SafeAreaConsumer
使用 SafeAreaInsetsContext.Consumer
代替。
SafeAreaContext
使用 SafeAreaInsetsContext
代替。
initialWindowSafeAreaInsets
使用 initialWindowMetrics
代替。
Web SSR
如果您在Web上进行服务器端渲染,可以使用 initialMetrics
根据用户的设备注入内插值和框架值,或简单地传递零值。由于内插值测量是异步的,否则它将破坏页面内容的呈现。
优化
如果可以,请使用 SafeAreaView
。它是本地实现的,因此在旋转设备时,没有来自异步桥接的延迟。
为了加快初始渲染,您可以从此软件包导入 initialWindowMetrics
,并将其作为提供程序上的 initialMetrics
属性设置,如Web SSR中所述。如果您的提供程序重新装载,或者您使用的是 react-native-navigation
,则无法这样做。
import {
SafeAreaProvider,
initialWindowMetrics,
} from 'react-native-safe-area-context';
function App() {
return (
<SafeAreaProvider initialMetrics={initialWindowMetrics}>
...
</SafeAreaProvider>
);
}
测试
该库包含一个内置的Jest模拟。它将默认使用以下指标:
{
frame: {
width: 320,
height: 640,
x: 0,
y: 0,
},
insets: {
left: 0,
right: 0,
bottom: 0,
top: 0,
},
}
要使用它,请将以下代码添加到jest设置文件中:
import mockSafeAreaContext from 'react-native-safe-area-context/jest/mock';
jest.mock('react-native-safe-area-context', () => mockSafeAreaContext);
为了更好地控制测试值,也可以将 initialMetrics
传递给 SafeAreaProvider
以提供框架和内插值的模拟数据。
export function TestSafeAreaProvider({ children }) {
return (
<SafeAreaProvider
initialMetrics={{
frame: { x: 0, y: 0, width: 0, height: 0 },
insets: { top: 0, left: 0, right: 0, bottom: 0 },
}}
>
{children}
</SafeAreaProvider>
);
}
贡献
请参阅贡献指南