使用 Expo UI 构建 SwiftUI 应用
编辑
了解如何使用 Expo UI 将 SwiftUI 集成到您的 Expo 应用中。
信息 可用于 SDK 54 及更高版本。
Expo UI 将 SwiftUI 带入 React Native。您可以使用现代 SwiftUI 原语来构建您的应用。
本指南涵盖了使用 Expo UI 将 SwiftUI 集成到您的 Expo 应用中的基础知识。

了解如何在您的 React Native 应用中使用新的 Expo UI 构建真实的 SwiftUI 视图。
特点
- SwiftUI 原语:Expo UI 不是另一个 UI 库。它将 SwiftUI 原语带到了 Expo。
- 1 对 1 映射:Expo UI 中的组件与 SwiftUI 视图具有 1 对 1 的映射。您可以轻松探索 SwiftUI 生态系统中的可用视图,例如 Explore SwiftUI 或 Libraried 应用,并找到相应的 Expo UI 组件。
- 全应用支持:Expo UI 旨在在整个应用中使用。您可以完全用 Expo UI 编写应用,同时保持灵活性。集成在组件级别进行。您还可以混合 React Native 组件、Expo UI 组件、DOM 组件 或使用
react-native-skia的自定义 2D 组件。
安装
您需要在 Expo 项目中安装 @expo/ui 包。运行以下命令进行安装:
- npx expo install @expo/ui使用
Expo UI 有多个可用的 SwiftUI 组件。您可以通过从 @expo/ui/swift-ui 导入它们来在您的应用中使用。然而,要从 React Native (UIKit) 跨越到 SwiftUI,您需要使用 Host 组件。Host 是 SwiftUI 视图的容器。您可以将其视为 DOM 中的 <svg> 或 react-native-skia 中的 <Canvas>。在底层,它使用 UIHostingController 在 UIKit 中渲染 SwiftUI 视图。
使用 Host 的基本用法
import { CircularProgress, Host } from '@expo/ui/swift-ui'; import { View, Text } from 'react-native'; export default function LoadingView() { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Host matchContents> <CircularProgress /> </Host> <Text>加载中...</Text> </View> ); }
使用 HStack 和 VStack
您还可以使用 HStack 和 VStack 组件在 SwiftUI 中构建整个布局。
import { CircularProgress, Host, HStack, LinearProgress, VStack } from '@expo/ui/swift-ui'; export default function LoadingView() { return ( <Host style={{ flex: 1, margin: 32 }}> <VStack spacing={32}> <HStack spacing={32}> <CircularProgress /> <CircularProgress color="orange" /> </HStack> <LinearProgress progress={0.5} /> <LinearProgress color="orange" progress={0.7} /> </VStack> </Host> ); }
修饰符
SwiftUI 修饰符 是自定义 SwiftUI 组件外观和行为的一种强大方式。Expo UI 也为 SwiftUI 组件提供修饰符。您可以从 @expo/ui/swift-ui/modifiers 导入修饰符,并将它们作为数组传递给 modifiers 属性。在下面的示例中,expo-mesh-gradient 和 glassEffect 修饰符结合在一起创建了液体玻璃文本。
注意:
glassEffect修饰符需要 Xcode 26+ 和 iOS 26+。
import { Host, Text } from '@expo/ui/swift-ui'; import { glassEffect, padding } from '@expo/ui/swift-ui/modifiers'; import { MeshGradientView } from 'expo-mesh-gradient'; import { View } from 'react-native'; export default function Page() { return ( <View style={{ flex: 1 }}> <MeshGradientView style={{ flex: 1 }} columns={3} rows={3} colors={['red', 'purple', 'indigo', 'orange', 'white', 'blue', 'yellow', 'green', 'cyan']} points={[ [0.0, 0.0], [0.5, 0.0], [1.0, 0.0], [0.0, 0.5], [0.5, 0.5], [1.0, 0.5], [0.0, 1.0], [0.5, 1.0], [1.0, 1.0], ]} /> <Host style={{ position: 'absolute', top: 0, right: 0, left: 0, bottom: 0 }}> <Text size={32} modifiers={[ padding({ all: 16, }), glassEffect({ glass: { variant: 'clear', }, }), ]}> Glass effect text </Text> </Host> </View> ); }
iOS 设置应用示例
结合 Expo UI 组件和修饰符,您可以构建类似于 iOS 设置应用的 UI。
import { Button, Form, Host, HStack, Image, Section, Spacer, Switch, Text, } from '@expo/ui/swift-ui'; import { background, clipShape, frame } from '@expo/ui/swift-ui/modifiers'; import { Link } from 'expo-router'; import { useState } from 'react'; export default function SettingsView() { const [isAirplaneMode, setIsAirplaneMode] = useState(true); return ( <Host style={{ flex: 1 }}> <Form> <Section> <HStack spacing={8}> <Image systemName="airplane" color="white" size={18} modifiers={[ frame({ width: 28, height: 28 }), background('#ffa500'), clipShape('roundedRectangle'), ]} /> <Text>Airplane Mode</Text> <Spacer /> <Switch value={isAirplaneMode} onValueChange={setIsAirplaneMode} /> </HStack> <Link href="/wifi" asChild> <Button> <HStack spacing={8}> <Image systemName="wifi" color="white" size={18} modifiers={[ frame({ width: 28, height: 28 }), background('#007aff'), clipShape('roundedRectangle'), ]} /> <Text color="primary">Wi-Fi</Text> <Spacer /> <Image systemName="chevron.right" size={14} color="secondary" /> </HStack> </Button> </Link> </Section> </Form> </Host> ); }
常见问题
我可以在 SwiftUI 组件中使用 flexbox 或其他样式吗?
Flexbox 样式可以应用于 Host 组件本身。然而,一旦进入 SwiftUI 上下文,Yoga 将不可用 — 布局应使用 <HStack> 和 <VStack> 来定义。
什么是 Host 组件?
Host 是 SwiftUI 视图的容器。你可以将其视为 DOM 中的 <svg> 或 react-native-skia 中的 <Canvas>。在底层,它使用 UIHostingController 在 UIKit 中渲染 SwiftUI 视图。
Expo UI 与 react-native-paper 或 react-native-elements 类似的库有什么不同?
Expo UI 不是“另一个” UI 库,也不是一个有观点的设计工具包。相反,它是一个原语库。它直接将原生 SwiftUI 和 Jetpack Compose 组件暴露给 JavaScript,而不是在 JavaScript 中重新实现或模拟 UI。
我可以在 Android 或 Web 上使用 @expo/ui/swift-ui 吗?
Expo UI 的第一个里程碑是实现 SwiftUI 与 Expo UI 之间的 1 对 1 映射。通用支持将在路线图的下一阶段到来。我们的优先事项是首先建立强大的 SwiftUI 支持,然后扩展到 Android 上的 Jetpack Compose 和 Web 上的 DOM 支持。
我可以在 SwiftUI 组件内部使用 React Native 组件吗?
是的,您可以将 React Native 组件作为 JSX 子元素放置在 Expo UI 组件中。Expo UI 自动为您创建一个 UIViewRepresentable 包装器。
然而,请记住,SwiftUI 布局系统的工作方式与 UIKit 不同,并且存在一些限制。根据苹果的文档:
SwiftUI 完全控制 UIKit 视图的center、bounds、frame和transform属性。请勿在您自己的代码中直接设置由UIViewRepresentable实例管理的视图的这些布局相关属性,因为这与 SwiftUI 冲突,并导致未定义行为。
请注意,一旦您渲染 React Native 组件,就会离开 SwiftUI 上下文。如果您想再次添加 Expo UI 组件,您需要重新引入一个 Host 包裹。
我们建议将 SwiftUI 布局保持自包含。互操作是可能的,但在界限清晰时效果最佳。
额外资源
有关 API 组件、方法等信息,请参见 Expo UI 参考。
我们最新的 Expo UI 示例
一个使用 Expo UI 复制 YVR 热巧克力节应用的示例应用
TVOS 对 Expo UI 的支持