使用 Expo UI 构建 SwiftUI 应用

编辑

了解如何使用 Expo UI 将 SwiftUI 集成到您的 Expo 应用中。

iOS
macOS
tvOS

信息 可用于 SDK 54 及更高版本

Expo UI 将 SwiftUI 带入 React Native。您可以使用现代 SwiftUI 原语来构建您的应用。

本指南涵盖了使用 Expo UI 将 SwiftUI 集成到您的 Expo 应用中的基础知识。

Expo UI iOS 液态玻璃教程
Expo UI iOS 液态玻璃教程

了解如何在您的 React Native 应用中使用新的 Expo UI 构建真实的 SwiftUI 视图。

特点

  • SwiftUI 原语:Expo UI 不是另一个 UI 库。它将 SwiftUI 原语带到了 Expo。
  • 1 对 1 映射:Expo UI 中的组件与 SwiftUI 视图具有 1 对 1 的映射。您可以轻松探索 SwiftUI 生态系统中的可用视图,例如 Explore SwiftUILibraried 应用,并找到相应的 Expo UI 组件。
  • 全应用支持:Expo UI 旨在在整个应用中使用。您可以完全用 Expo UI 编写应用,同时保持灵活性。集成在组件级别进行。您还可以混合 React Native 组件Expo UI 组件DOM 组件 或使用 react-native-skia 的自定义 2D 组件。

安装

您需要在 Expo 项目中安装 @expo/ui 包。运行以下命令进行安装:

Terminal
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 的基本用法

SwiftUI loading view
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> ); }

使用 HStackVStack

您还可以使用 HStackVStack 组件在 SwiftUI 中构建整个布局。

SwiftUI loading with HStack and VStack
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-gradientglassEffect 修饰符结合在一起创建了液体玻璃文本。

注意glassEffect 修饰符需要 Xcode 26+ 和 iOS 26+。

SwiftUI modifiers
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。

SwiftUI Form example to build iOS Settings app
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-paperreact-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 视图的 centerboundsframetransform 属性。请勿在您自己的代码中直接设置由 UIViewRepresentable 实例管理的视图的这些布局相关属性,因为这与 SwiftUI 冲突,并导致未定义行为。

请注意,一旦您渲染 React Native 组件,就会离开 SwiftUI 上下文。如果您想再次添加 Expo UI 组件,您需要重新引入一个 Host 包裹。

我们建议将 SwiftUI 布局保持自包含。互操作是可能的,但在界限清晰时效果最佳。

我是 SwiftUI 开发者。我为什么要学习 Expo UI?

因为 React 的承诺是 “学习一次,随处编写”,现在扩展到了 SwiftUI 和 Jetpack Compose。通过 Expo UI,您可以运用您的 SwiftUI 知识来构建在 React Native 生态系统中运行的应用,扩展到通过 DOM 组件 的 Web,甚至集成 2D3D 渲染。该系统具有足够的灵活性,不同部分的应用可以使用不同的方法——在组件级别为您提供无缝集成。

额外资源

Expo UI 参考

有关 API 组件、方法等信息,请参见 Expo UI 参考。

Expo UI 示例

我们最新的 Expo UI 示例

Hot Chocolate 应用示例

一个使用 Expo UI 复制 YVR 热巧克力节应用的示例应用

Expo UI 示例复制到 TV

TVOS 对 Expo UI 的支持