This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.

包装第三方原生库

编辑页面

了解如何使用 Expo Modules API 围绕两个独立的原生库创建一个简单的包装器。


Expo 模块使得在 React Native 项目中轻松使用为 Android 和 iOS 构建的原生外部库成为可能。本教程重点介绍如何利用 Expo Modules API,使用两个可在两个原生平台上访问的相似库创建径向图表。

iOS 库受到 Android 库的启发,因此它们都具有相似的 API 和功能。这使它们成为本教程的一个很好的示例。

如何包装原生库
如何包装原生库

在这个视频中,你将学习如何使用 Expo Modules API 包装原生库。


1

创建一个新模块

以下步骤假设新模块是在一个新的 Expo 项目中创建的。不过,你也可以按照替代说明在现有项目中创建新模块。

或者,你可以将新模块作为现有 Expo 项目目录中的一个视图来使用。在项目目录中运行以下命令:

Terminal
npx create-expo-module --local expo-radial-chart

现在,打开新创建的 modules/expo-radial-chart 目录,开始编辑原生代码。

2

运行示例项目

为了验证一切是否正常运行,让我们运行示例项目。

如果你是从现有 Expo 项目开始的,请在 Expo 项目的根目录中运行以下命令:

Terminal
# 在 Android 上运行 example-expo-app
npx expo run:android

# 在 iOS 上运行示例应用
npx expo run:ios

3

添加原生依赖

通过编辑 expo-radial-chart/android/build.gradleexpo-radial-chart/ios/ExpoRadialChart.podspec 文件,将原生依赖添加到模块中:

你是否想使用 .aar 依赖?

android 目录中,再创建一个名为 libs 的目录,并将 .aar 文件放入其中。然后,通过 autolinking 将该文件作为 Gradle 项目添加:

最后,将依赖添加到 android/build.gradle 文件中的 dependencies 列表里,并使用依赖指定的名称,前面加上 ${project.name}$ 前缀:

你是否想使用 .xcframework.framework 依赖?

在 iOS 上,你也可以通过使用 vendored_frameworks 配置选项来使用以 framework 形式打包的依赖。

添加 framework 后,请确保 source_files 选项的文件模式不会匹配 framework 中的任何文件。实现这一点的一种方法是将 iOS 源 Swift 文件(即 ExpoRadialChartView.swiftExpoRadialChartModule.swift)移动到一个与放置 framework 的位置分开的 src 目录中,并将 source_files 选项更新为只匹配 src 目录:

你的 ios 目录最终应具有类似以下的文件结构:

Frameworks
MyFramework.framework
src
ExpoRadialChartView.swift
ExpoRadialChartModule.swift
ExpoRadialChart.podspec

4

定义一个 API

要在应用中使用该模块,请定义这些 props 的类型。它接受一个系列列表——每个系列都包含一个颜色和一个百分比值。

src/ExpoRadialChart.types.ts
import { ViewStyle } from 'react-native/types'; export type ChangeEventPayload = { value: string; }; type Series = { color: string; percentage: number; }; export type ExpoRadialChartViewProps = { style?: ViewStyle; data: Series[]; };

由于本示例中该模块没有为 web 实现,我们将替换 src/ExpoRadialChartView.web.tsx 文件:

src/ExpoRadialChartView.web.tsx
import * as React from 'react'; export default function ExpoRadialChartView() { return <div>未实现</div>; }

5

在 Android 上实现模块

现在你可以通过编辑占位文件并进行以下更改来实现原生功能:

  1. 创建一个 PieChart 实例,并将其 layoutParams 设置为与父视图一致。然后,使用 addView 函数将其添加到视图层级中。
  2. 定义一个接受 Series 对象列表的 setChartData 函数。你可以遍历该列表,为每个系列创建一个 PieEntry,并将颜色存储在一个单独的列表中。
  3. 创建一个 PieDataSet,使用它创建一个 PieData 对象,并将其设置为 PieChart 实例的数据。
android/src/main/java/expo/modules/radialchart/ExpoRadialChartView.kt
package expo.modules.radialchart import android.content.Context import android.graphics.Color import androidx.annotation.ColorInt import com.github.mikephil.charting.charts.PieChart import com.github.mikephil.charting.data.PieData import com.github.mikephil.charting.data.PieDataSet import com.github.mikephil.charting.data.PieEntry import expo.modules.kotlin.AppContext import expo.modules.kotlin.records.Field import expo.modules.kotlin.records.Record import expo.modules.kotlin.views.ExpoView class Series : Record { @Field val color: String = "#ff0000" @Field val percentage: Float = 0.0f } class ExpoRadialChartView(context: Context, appContext: AppContext) : ExpoView(context, appContext) { internal val chartView = PieChart(context).also { it.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT) addView(it) } fun setChartData(data: ArrayList<Series>) { val entries: ArrayList<PieEntry> = ArrayList() val colors: ArrayList<Int> = ArrayList() for (series in data) { entries.add(PieEntry(series.percentage)) colors.add(Color.parseColor(series.color)) } val dataSet = PieDataSet(entries, "DataSet"); dataSet.colors = colors; val pieData = PieData(dataSet); chartView.data = pieData; chartView.invalidate(); } }

你还需要使用 Prop 函数来定义 data prop,并在 prop 变化时调用原生的 setChartData 函数:

android/src/main/java/expo/modules/radialchart/ExpoRadialChartModule.kt
package expo.modules.radialchart import expo.modules.kotlin.modules.Module import expo.modules.kotlin.modules.ModuleDefinition class ExpoRadialChartModule : Module() { override fun definition() = ModuleDefinition { Name("ExpoRadialChart") View(ExpoRadialChartView::class) { Prop("data") { view: ExpoRadialChartView, prop: ArrayList<Series> -> view.setChartData(prop); } } } }

6

在 iOS 上实现模块

现在你可以通过编辑占位文件并进行以下更改来实现原生功能:

  1. 创建一个新的 PieChartView 实例,并使用 addSubview 函数将其添加到视图层级中。
  2. 设置 clipsToBounds 属性,并重写 layoutSubviews 函数,以确保图表视图始终与父视图大小相同。
  3. 创建一个接受系列列表的 setChartData 函数,使用数据创建一个 PieChartDataSet 实例,并将其赋值给 PieChartView 实例的 data 属性。
ios/ExpoRadialChartView.swift
import ExpoModulesCore import DGCharts struct Series: Record { @Field var color: UIColor = UIColor.black @Field var percentage: Double = 0 } class ExpoRadialChartView: ExpoView { let chartView = PieChartView() required init(appContext: AppContext? = nil) { super.init(appContext: appContext) clipsToBounds = true addSubview(chartView) } override func layoutSubviews() { chartView.frame = bounds } func setChartData(data: [Series]) { let set1 = PieChartDataSet(entries: data.map({ (series: Series) -> PieChartDataEntry in return PieChartDataEntry(value: series.percentage) })) set1.colors = data.map({ (series: Series) -> UIColor in return series.color }) let chartData: PieChartData = [set1] chartView.data = chartData } }

你还需要使用 Prop 函数来定义 data prop,并在 prop 变化时调用原生的 setChartData 函数:

ios/ExpoRadialChartModule.swift
import ExpoModulesCore public class ExpoRadialChartModule: Module { public func definition() -> ModuleDefinition { Name("ExpoRadialChart") View(ExpoRadialChartView.self) { Prop("data") { (view: ExpoRadialChartView, prop: [Series]) in view.setChartData(data: prop) } } } }

7

编写一个使用该模块的示例应用

你可以更新 src/app 目录中的应用来测试该模块。使用 ExpoRadialChartView 组件渲染一个包含三个扇区的饼图:

src/app/index.tsx
import { ExpoRadialChartView } from '@/modules/expo-radial-chart'; import { StyleSheet } from 'react-native'; export default function App() { return ( <ExpoRadialChartView style={styles.container} data={[ { color: '#ff0000', percentage: 0.5, }, { color: '#00ff00', percentage: 0.2, }, { color: '#0000ff', percentage: 0.3, }, ]} /> ); } const styles = StyleSheet.create({ container: { flex: 1, }, });

8

重新构建并启动你的应用

为了确保你的应用在两个平台上都能成功构建,请重新运行第 2 步中的构建命令。应用在任一平台成功构建后,你会看到一个包含三个扇区的饼图:

恭喜!你已经使用 Expo Modules API 创建了第一个围绕两个独立第三方原生库的简单封装。

下一步

Expo 模块 API 参考

使用 Kotlin 和 Swift 创建原生模块的参考。