This is documentation for the next SDK version. For up-to-date documentation, see the latest version (SDK 55).
RNHostView
一个允许在 Jetpack Compose 中使用 React Native 视图的组件。
For the complete documentation index, see llms.txt. Use this Use this file to discover all available pages.
一个组件,可在 React Native 视图渲染于 Jetpack Compose 组件内部时,启用正确的布局行为。它通过更新 shadow node 的大小,将 Jetpack Compose 的布局信息同步回 React Native 的 Yoga 布局系统。
当 React Native 视图放置在诸如 ModalBottomSheet、Card、Row、Column 等 Jetpack Compose 组件内部时,布局系统需要进行通信。RNHostView 负责弥合这一差距:
- 使用
matchContents:shadow node 的大小会设置为与子 React Native 视图的固有大小一致,从而允许 Jetpack Compose 父组件根据 React Native 内容来确定自身大小。 - 不使用
matchContents:shadow node 的大小会设置为与父 Jetpack Compose 视图的大小一致,从而允许 React Native 内容填充可用空间(对flex: 1布局很有用)。
安装
- npx expo install @expo/uiIf you are installing this in an existing React Native app, make sure to install expo in your project.
用法
使用 matchContents 的基本用法
当你希望 Jetpack Compose 父组件根据 React Native 内容来确定自身大小时,请使用 matchContents。
import { useState } from 'react'; import { Pressable, Text as RNText, View } from 'react-native'; import { Host, Card, Column, Row, RNHostView, Text } from '@expo/ui/jetpack-compose'; import { fillMaxWidth, padding } from '@expo/ui/jetpack-compose/modifiers'; function Example() { const [counter, setCounter] = useState(0); return ( <Host style={{ flex: 1 }}> <Card modifiers={[fillMaxWidth()]}> <Column verticalArrangement={{ spacedBy: 12 }} modifiers={[padding(16, 16, 16, 16)]}> <Text>将 RN 组件与 Compose 混合使用</Text> <Row horizontalArrangement={{ spacedBy: 24 }} verticalAlignment="center"> <RNHostView matchContents> <Pressable onPress={() => setCounter(prev => prev - 1)} style={{ height: 50, width: 50, borderRadius: 100, justifyContent: 'center', alignItems: 'center', backgroundColor: '#9B59B6', }}> <RNText style={{ color: 'white', fontSize: 24 }}>-</RNText> </Pressable> </RNHostView> <Text>{counter}</Text> <RNHostView matchContents> <Pressable onPress={() => setCounter(prev => prev + 1)} style={{ height: 50, width: 50, borderRadius: 100, justifyContent: 'center', alignItems: 'center', backgroundColor: '#9B59B6', }}> <RNText style={{ color: 'white', fontSize: 24 }}>+</RNText> </Pressable> </RNHostView> </Row> </Column> </Card> </Host> ); }
不使用 matchContents 的弹性内容
当你的 React Native 内容中使用 flex: 1 时,请省略 matchContents 属性,这样内容就会填充可用的 Jetpack Compose 空间。
import { Text as RNText, View } from 'react-native'; import { Host, Card, Column, Row, RNHostView, Text } from '@expo/ui/jetpack-compose'; import { fillMaxWidth, padding, size } from '@expo/ui/jetpack-compose/modifiers'; function Example() { return ( <Host style={{ flex: 1 }}> <Card modifiers={[fillMaxWidth()]}> <Column verticalArrangement={{ spacedBy: 12 }} modifiers={[padding(16, 16, 16, 16)]}> <Text>带有 flex: 1 子组件的 RN 组件</Text> <Row horizontalArrangement={{ spacedBy: 20 }} modifiers={[size(100, 100)]}> <RNHostView> <View style={{ flex: 1, backgroundColor: '#9B59B6', borderRadius: 10, }} /> </RNHostView> </Row> </Column> </Card> </Host> ); }
在 ModalBottomSheet 中的用法
RNHostView 在 ModalBottomSheet 内部同样表现良好,可用于展示可交互的 React Native 内容。
import { useRef, useState } from 'react'; import { Pressable, Text as RNText, View } from 'react-native'; import { Host, ModalBottomSheet, Button, Column, RNHostView, Text } from '@expo/ui/jetpack-compose'; import type { ModalBottomSheetRef } from '@expo/ui/jetpack-compose'; import { padding } from '@expo/ui/jetpack-compose/modifiers'; function Example() { const [visible, setVisible] = useState(false); const sheetRef = useRef<ModalBottomSheetRef>(null); const hideSheet = async () => { await sheetRef.current?.hide(); setVisible(false); }; return ( <Host matchContents> <Button onClick={() => setVisible(true)}> <Text>打开底部抽屉</Text> </Button> {visible && ( <ModalBottomSheet ref={sheetRef} onDismissRequest={() => setVisible(false)}> <Column verticalArrangement={{ spacedBy: 16 }} modifiers={[padding(16, 16, 16, 16)]}> <Text>在底部抽屉中混合使用 Compose + RN</Text> <RNHostView matchContents> <View> <RNText style={{ fontSize: 18, fontWeight: 'bold', marginBottom: 8 }}> React Native 内容 </RNText> <Pressable style={{ backgroundColor: '#007AFF', padding: 12, borderRadius: 8, alignItems: 'center', }} onPress={hideSheet}> <RNText style={{ color: 'white', fontWeight: '600' }}>关闭</RNText> </Pressable> </View> </RNHostView> </Column> </ModalBottomSheet> )} </Host> ); }
底部抽屉中的弹性 React Native 内容
使用不带 matchContents 的 RNHostView,让 React Native 视图填充抽屉中的剩余空间。结合父 Column 上的 height 修饰符来控制抽屉大小。
import { useRef, useState } from 'react'; import { Text as RNText, View } from 'react-native'; import { Host, ModalBottomSheet, Button, Column, RNHostView, Text } from '@expo/ui/jetpack-compose'; import type { ModalBottomSheetRef } from '@expo/ui/jetpack-compose'; import { height, padding } from '@expo/ui/jetpack-compose/modifiers'; function Example() { const [visible, setVisible] = useState(false); const sheetRef = useRef<ModalBottomSheetRef>(null); return ( <Host matchContents> <Button onClick={() => setVisible(true)}> <Text>打开弹性内容抽屉</Text> </Button> {visible && ( <ModalBottomSheet ref={sheetRef} onDismissRequest={() => setVisible(false)} skipPartiallyExpanded> <Column modifiers={[height(400), padding(16, 16, 16, 16)]}> <RNHostView> <View style={{ flex: 1, backgroundColor: '#9B59B6', borderRadius: 10 }}> <RNText style={{ color: 'white', fontSize: 18, fontWeight: 'bold', padding: 16, }}> React Native 内容(flex: 1) </RNText> </View> </RNHostView> </Column> </ModalBottomSheet> )} </Host> ); }
API
import { RNHostView } from '@expo/ui/jetpack-compose';
Component
Type: React.Element<RNHostProps>
boolean • Default: falseWhen true, the RNHost will update its size in the Jetpack Compose view tree to match the children's size.
When false, the RNHost will use the size of the parent Jetpack Compose View.
Can be only set once on mount.