使用 SwiftUI 扩展
编辑页面
了解如何创建可与 Expo UI 集成的自定义 SwiftUI 组件和修饰符。
For the complete documentation index, see llms.txt. Use this Use this file to discover all available pages.
本指南说明如何创建可与 Expo UI 无缝集成的自定义 SwiftUI 组件和修饰符。
前提条件
在开始之前,请确保你已具备以下条件:
- 项目中已安装
@expo/ui。有关更多信息,请参阅使用 Expo UI 构建 SwiftUI 应用。 - 你的应用有一个开发构建(Expo Go 中不可用 Expo UI)
- 对 Expo Modules API 和 SwiftUI 有基本了解
- npx expo install @expo/ui创建自定义组件
项目设置
1
在你的项目中创建一个本地 Expo 模块:
- npx create-expo-module@latest --local my-ui2
在模块的 podspec 文件中将 ExpoUI 添加为依赖项:
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 视图分为两部分创建:
- Props 类:继承
ExpoUI中的UIBaseViewProps,以自动支持modifiers属性 - View 结构体:遵循
ExpoSwiftUI.View协议,该协议要求提供一个@ObservedObjectprops 属性和一个body
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 使用:
import ExpoModulesCore import ExpoUI public class MyUiModule: Module { public func definition() -> ModuleDefinition { Name("MyUi") ExpoUIView(MyCustomView.self) } }
5
创建一个包装组件,用于连接修饰符与事件处理。createViewModifierEventListener 工具可使 onTapGesture 和 onAppear 之类的基于事件的修饰符与你的自定义视图配合工作:
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 内置修饰符一起使用:
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
创建一个符合 ViewModifier 和 Record 的修饰符结构体:
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 渲染线程发生竞态条件:
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 函数:
import { createModifier } from '@expo/ui/swift-ui/modifiers'; export const customBorder = (params: { color?: string; width?: number; cornerRadius?: number }) => createModifier('customBorder', params);
4
从你的模块中导出该修饰符:
export { MyCustomView, type MyCustomViewProps } from './src/MyCustomView'; export { customBorder } from './src/modifiers';
使用自定义修饰符
你的自定义修饰符可与任何 ExpoUI 组件一起使用:
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 包分享给他人使用