RN主机视图
一个可以在 SwiftUI 中使用 React Native 视图的组件。
一个组件,当 React Native 视图在 SwiftUI 组件内渲染时,可以实现正确的布局行为。它通过更新 shadow 节点的大小,将布局信息从 SwiftUI 同步回 React Native 的 Yoga 布局系统。
🌐 A component that enables proper layout behavior when React Native views are rendered inside SwiftUI components. It syncs layout information from SwiftUI back to React Native's Yoga layout system by updating the shadow node size.
当 React Native 视图被放置在 SwiftUI 组件中,例如 BottomSheet、Popover 或 HStack 等时,布局系统需要进行通信。RNHostView 架起了这道桥梁:
🌐 When React Native views are placed inside SwiftUI components like BottomSheet, Popover or HStack and so on, the layout systems need to communicate. RNHostView bridges this gap:
- 使用
matchContents:阴影节点的大小设置为匹配子 React Native 视图的固有大小,从而允许 SwiftUI 父视图根据 React Native 内容来调整自身大小。 - 没有
matchContents:影子节点大小设置为与父 SwiftUI 视图的大小相匹配,使 React Native 内容能够填充可用空间(对于flex: 1布局很有用)。
安装
🌐 Installation
- npx expo install @expo/uiIf you are installing this in an existing React Native app, make sure to install expo in your project.
用法
🌐 Usage
matchContents 的基本用法
🌐 Basic usage with matchContents
当你希望 SwiftUI 父视图根据 React Native 内容来调整自身大小时,使用 matchContents。
🌐 Use matchContents when you want the SwiftUI parent to size itself based on the React Native content.
import { useState } from 'react'; import { Pressable, Text, View } from 'react-native'; import { Host, BottomSheet, Button, RNHostView } from '@expo/ui/swift-ui'; function Example() { const [isPresented, setIsPresented] = useState(false); return ( <Host style={{ flex: 1 }}> <Button label="Open Sheet" onPress={() => setIsPresented(true)} /> <BottomSheet isOpened={isPresented} onIsOpenedChange={setIsPresented}> <RNHostView matchContents> <View style={{ padding: 24 }}> <Text style={{ fontSize: 18, fontWeight: 'bold' }}>React Native Content</Text> <Pressable style={{ backgroundColor: '#007AFF', padding: 12, borderRadius: 8, marginTop: 16 }} onPress={() => setIsPresented(false)}> <Text style={{ color: 'white', textAlign: 'center' }}>Close</Text> </Pressable> </View> </RNHostView> </BottomSheet> </Host> ); }
没有匹配内容的灵活内容
🌐 Flexible content without matchContents
在你的 React Native 内容中使用 flex: 1 时,省略 matchContents 属性,这样内容就会填满可用的 SwiftUI 空间。
🌐 When using flex: 1 in your React Native content, omit the matchContents prop so the content fills the available SwiftUI space.
import { useState } from 'react'; import { Text, View } from 'react-native'; import { Host, BottomSheet, Button, RNHostView } from '@expo/ui/swift-ui'; function Example() { const [isPresented, setIsPresented] = useState(false); return ( <Host style={{ flex: 1 }}> <Button label="Open Sheet" onPress={() => setIsPresented(true)} /> <BottomSheet isOpened={isPresented} onIsOpenedChange={setIsPresented} presentationDetents={['medium', 'large']}> <RNHostView> <View style={{ flex: 1, backgroundColor: '#007AFF', padding: 24 }}> <Text style={{ color: 'white', fontSize: 18 }}> This content fills the available space </Text> </View> </RNHostView> </BottomSheet> </Host> ); }
与弹出框一起使用
🌐 Usage with Popover
RNHostView 在 Popover 内部工作良好,可显示互动的 React Native 内容。
import { useState } from 'react'; import { Pressable, Text, View } from 'react-native'; import { Host, Button, Popover, RNHostView } from '@expo/ui/swift-ui'; function Example() { const [isPresented, setIsPresented] = useState(false); const [counter, setCounter] = useState(0); return ( <Host style={{ flex: 1 }}> <Popover isPresented={isPresented} onIsPresentedChange={setIsPresented}> <Popover.Trigger> <Button onPress={() => setIsPresented(true)} label="Show Popover" /> </Popover.Trigger> <Popover.Content> <RNHostView matchContents> <View style={{ padding: 24 }}> <Text style={{ fontSize: 16, fontWeight: 'bold', marginBottom: 8 }}> React Native Content </Text> <Text style={{ color: '#666', marginBottom: 12 }}>Counter: {counter}</Text> <Pressable style={{ backgroundColor: '#007AFF', padding: 12, borderRadius: 8, alignItems: 'center', }} onPress={() => setCounter(counter + 1)}> <Text style={{ color: 'white', fontWeight: '600' }}>Increment</Text> </Pressable> </View> </RNHostView> </Popover.Content> </Popover> </Host> ); }
应用接口
🌐 API
import { RNHostView } from '@expo/ui/swift-ui';
Component
Type: React.Element<RNHostViewProps>