RNHostView
一个组件,可在 SwiftUI 中启用 React Native 视图。
iOS
tvOS
Included in Expo Go
For the complete documentation index, see llms.txt. Use this file to discover all available pages.
一个组件,用于在 React Native 视图渲染于 SwiftUI 组件内部时,启用正确的布局行为。它通过更新 shadow node 的尺寸,将 SwiftUI 的布局信息同步回 React Native 的 Yoga 布局系统。
当 React Native 视图被放置在 BottomSheet、Popover 或 HStack 等 SwiftUI 组件中时,两个布局系统需要进行通信。RNHostView 用于弥合这一差距:
- 使用
matchContents时:shadow node 的尺寸会被设置为匹配子 React Native 视图的固有尺寸,使 SwiftUI 父组件能够根据 React Native 内容来确定自身大小。 - 不使用
matchContents时:shadow node 的尺寸会被设置为匹配父 SwiftUI 视图的尺寸,使 React Native 内容能够填充可用空间(适用于flex: 1布局)。
安装
Terminal
- npx expo install @expo/uiIf you are installing this in an existing React Native app, make sure to install expo in your project.
用法
使用 matchContents 的基础用法
当你希望 SwiftUI 父组件根据 React Native 内容来确定自身大小时,请使用 matchContents。
RNHostView with matchContents
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="打开抽屉" onPress={() => setIsPresented(true)} /> <BottomSheet isOpened={isPresented} onIsOpenedChange={setIsPresented}> <RNHostView matchContents> <View style={{ padding: 24 }}> <Text style={{ fontSize: 18, fontWeight: 'bold' }}>React Native 内容</Text> <Pressable style={{ backgroundColor: '#007AFF', padding: 12, borderRadius: 8, marginTop: 16 }} onPress={() => setIsPresented(false)}> <Text style={{ color: 'white', textAlign: 'center' }}>关闭</Text> </Pressable> </View> </RNHostView> </BottomSheet> </Host> ); }
不使用 matchContents 的灵活内容
当你的 React Native 内容使用 flex: 1 时,请省略 matchContents 属性,这样内容就会填充可用的 SwiftUI 空间。
RNHostView with flex content
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="打开抽屉" 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 }}> 此内容会填充可用空间 </Text> </View> </RNHostView> </BottomSheet> </Host> ); }
在 Popover 中使用
RNHostView 在 Popover 内部也能很好地工作,用于显示交互式 React Native 内容。
RNHostView in Popover
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="显示 Popover" /> </Popover.Trigger> <Popover.Content> <RNHostView matchContents> <View style={{ padding: 24 }}> <Text style={{ fontSize: 16, fontWeight: 'bold', marginBottom: 8 }}> React Native 内容 </Text> <Text style={{ color: '#666', marginBottom: 12 }}>计数器:{counter}</Text> <Pressable style={{ backgroundColor: '#007AFF', padding: 12, borderRadius: 8, alignItems: 'center', }} onPress={() => setCounter(counter + 1)}> <Text style={{ color: 'white', fontWeight: '600' }}>增加</Text> </Pressable> </View> </RNHostView> </Popover.Content> </Popover> </Host> ); }
API
import { RNHostView } from '@expo/ui/swift-ui';
Component
Type: React.Element<RNHostViewProps>