使用 SwiftUI 扩展
编辑页面
了解如何创建可与 Expo UI 集成的自定义 SwiftUI 组件和修饰符。
For the complete documentation index, see llms.txt. Use this file to discover all available pages.
本指南说明如何创建可与 Expo UI 无缝集成的自定义 SwiftUI 组件和修饰符。
3 requirements
3 requirements
1.
@expo/ui 已安装在你的项目中安装 @expo/ui。更多信息请参阅 使用 Expo UI 构建 SwiftUI 应用。
- npx expo install @expo/ui2.
Expo Go 中不提供 Expo UI。请为你的应用创建一个开发构建。
3.
建议对 Expo Modules API 和 SwiftUI 有基本了解。
创建自定义组件
项目设置
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 包分享给他人使用