使用 SwiftUI 扩展

编辑页面

了解如何创建可与 Expo UI 集成的自定义 SwiftUI 组件和修饰符。

iOS
tvOS

For the complete documentation index, see llms.txt. Use this Use this file to discover all available pages.

本指南说明如何创建可与 Expo UI 无缝集成的自定义 SwiftUI 组件和修饰符。

前提条件

在开始之前,请确保你已具备以下条件:

Terminal
npx expo install @expo/ui

创建自定义组件

项目设置

1

在你的项目中创建一个本地 Expo 模块:

Terminal
npx create-expo-module@latest --local my-ui

2

在模块的 podspec 文件中将 ExpoUI 添加为依赖项:

my-ui/ios/MyUi.podspec
Pod::Spec.new do |s| s.name = 'MyUi' s.version = '1.0.0' s.summary = '扩展 Expo UI 的自定义 UI 组件' # ... 其他配置 # 添加 ExpoUI 依赖 s.dependency 'ExpoUI' # ... 其他配置 end

创建 SwiftUI 视图

3

将你的 SwiftUI 视图分为两部分创建:

  1. Props 类:继承 ExpoUI 中的 UIBaseViewProps,以自动支持 modifiers 属性
  2. View 结构体:遵循 ExpoSwiftUI.View 协议,该协议要求提供一个 @ObservedObject props 属性和一个 body
my-ui/ios/MyCustomView.swift
import SwiftUI import ExpoModulesCore import ExpoUI final class MyCustomViewProps: UIBaseViewProps { @Field var title: String = "" } struct MyCustomView: ExpoSwiftUI.View { @ObservedObject public var props: MyCustomViewProps var body: some View { VStack { Text(props.title) .font(.headline) Children() // 渲染 React 子组件 } } }

4

在模块中使用 ExpoUIView 注册该视图。这会为你的 SwiftUI 视图包装修饰符支持,并使其可供 JavaScript 使用:

my-ui/ios/MyUiModule.swift
import ExpoModulesCore import ExpoUI public class MyUiModule: Module { public func definition() -> ModuleDefinition { Name("MyUi") ExpoUIView(MyCustomView.self) } }

5

创建一个包装组件,用于连接修饰符与事件处理。createViewModifierEventListener 工具可使 onTapGestureonAppear 之类的基于事件的修饰符与你的自定义视图配合工作:

my-ui/src/MyCustomView.tsx
import { requireNativeView } from 'expo'; import { type CommonViewModifierProps } from '@expo/ui/swift-ui'; import { createViewModifierEventListener } from '@expo/ui/swift-ui/modifiers'; export interface MyCustomViewProps extends CommonViewModifierProps { title: string; children?: React.ReactNode; } const NativeMyCustomView = requireNativeView<MyCustomViewProps>('MyUi', 'MyCustomView'); export function MyCustomView({ modifiers, ...restProps }: MyCustomViewProps) { return ( <NativeMyCustomView modifiers={modifiers} {...(modifiers ? createViewModifierEventListener(modifiers) : undefined)} {...restProps} /> ); }

使用你的自定义组件

你的自定义组件现在可与所有 ExpoUI 内置修饰符一起使用:

app/index.tsx
import { Host, Text } from '@expo/ui/swift-ui'; import { padding, cornerRadius, background } from '@expo/ui/swift-ui/modifiers'; import { MyCustomView } from './modules/my-ui'; export default function App() { return ( <Host style={{ flex: 1 }}> <MyCustomView title="Hello World" modifiers={[padding({ all: 16 }), cornerRadius(12), background('#f0f0f0')]}> <Text>子内容</Text> </MyCustomView> </Host> ); }

创建自定义修饰符

你还可以创建可与任何 Expo UI 组件配合使用的自定义修饰符。

修饰符是 SwiftUI 用来配置视图样式、布局、行为等内容的方式。更多信息请参阅 Apple 的 ViewModifier 文档

原生修饰符实现

1

创建一个符合 ViewModifierRecord 的修饰符结构体:

my-ui/ios/CustomBorderModifier.swift
import SwiftUI import ExpoModulesCore import ExpoUI struct CustomBorderModifier: ViewModifier, Record { @Field var color: Color = .red @Field var width: CGFloat = 2 @Field var cornerRadius: CGFloat = 0 func body(content: Content) -> some View { content .overlay( RoundedRectangle(cornerRadius: cornerRadius) .stroke(color, lineWidth: width) ) } }

2

在模块定义中使用 ViewModifierRegistry 注册你的修饰符。使用 OnCreate 进行注册、OnDestroy 进行注销,以避免与 SwiftUI 渲染线程发生竞态条件:

my-ui/ios/MyUiModule.swift
import ExpoModulesCore import ExpoUI public class MyUiModule: Module { public func definition() -> ModuleDefinition { Name("MyUi") OnCreate { ViewModifierRegistry.register("customBorder") { params, appContext, _ in return try CustomBorderModifier(from: params, appContext: appContext) } } OnDestroy { ViewModifierRegistry.unregister("customBorder") } ExpoUIView(MyCustomView.self) } }

JavaScript 修饰符函数

3

创建一个生成修饰符配置的 TypeScript 函数:

my-ui/src/modifiers.ts
import { createModifier } from '@expo/ui/swift-ui/modifiers'; export const customBorder = (params: { color?: string; width?: number; cornerRadius?: number }) => createModifier('customBorder', params);

4

从你的模块中导出该修饰符:

my-ui/index.ts
export { MyCustomView, type MyCustomViewProps } from './src/MyCustomView'; export { customBorder } from './src/modifiers';

使用自定义修饰符

你的自定义修饰符可与任何 ExpoUI 组件一起使用:

app/index.tsx
import { Host, Text, VStack } from '@expo/ui/swift-ui'; import { padding } from '@expo/ui/swift-ui/modifiers'; import { customBorder } from './modules/my-ui'; export default function App() { return ( <Host style={{ flex: 1 }}> <VStack modifiers={[ padding({ all: 20 }), customBorder({ color: '#FF6B35', width: 3, cornerRadius: 8 }), ]}> <Text>这有一个自定义边框!</Text> </VStack> </Host> ); }

后续步骤

恭喜!你已经学会了如何使用自定义 SwiftUI 组件和修饰符扩展 Expo UI。你的自定义组件现在可以与内置修饰符系统无缝集成。

接下来你可以考虑构建以下内容:

  • 使用 Expo UI 自带的内置 SwiftUI 组件
  • 为应用特定的样式模式构建自定义修饰符
  • 封装第三方 SwiftUI 库以在 React Native 中使用
  • 将你的组件作为 npm 包分享给他人使用