☰
AwesomeExample:react-native-image-crop-picker 官方示例应用的完整运行指南
2026/10/15 3:33:47 网站建设 项目流程
  • 移动开发
  • 图像处理

【免费下载链接】react-native-image-crop-picker

iOS/Android image picker with support for camera, video, configurable compression, multiple images and cropping

项目地址:https://gitcode.com/gh_mirrors/re/react-native-image-crop-picker
点击查看免费下载

导读

本文围绕仓库中的 AwesomeExample/README.md 展开,以官方示例应用 AwesomeExample 为载体,完整讲解如何从零启动 Metro、在 Android 与 iOS 上构建运行一个集成了 react-native-image-crop-picker 的 React Native 0.79 项目,并通过源码级分析带你读懂示例中openPicker、openCamera、openCropper、clean等核心 API 的实际用法、裁剪与压缩等高级参数配置,以及双平台权限配置与原生集成细节。读完本文,你将能够独立跑通一个"选图 + 拍照 + 裁剪 + 多选 + 视频 + 临时文件清理"的完整图片选择应用,并清楚每个参数背后对应的原生实现原理。

<output_image></output_image>

一、AwesomeExample 是什么

AwesomeExample 是本仓库 react-native-image-crop-picker 自带的官方示例工程,位于 AwesomeExample 目录。它并不是一个普通的"Hello World",而是一个几乎覆盖了图片选择器全部能力的完整演示应用。

从 AwesomeExample/package.json 可以看到它的依赖配置:

"dependencies": { "react": "19.0.0", "react-native": "0.79.2", "react-native-image-crop-picker": "../", "react-native-video": "^6.14.1" }

关键点在于"react-native-image-crop-picker": "../"——它通过相对路径直接引用仓库根目录的库源码,因此修改库代码后可以即时在示例中验证效果,这正是它作为库的活体文档的价值所在。另外它额外引入了react-native-video,用于在选中视频后播放预览。

项目入口逻辑在 AwesomeExample/index.js 与 AwesomeExample/app.json 中:通过AppRegistry.registerComponent(appName, () => App)注册名为AwesomeExample的应用组件,而真正的业务代码全部集中在 AwesomeExample/App.tsx(下文会逐行拆解)。

二、启动前准备:环境与依赖

1. 环境要求

  • Node.js 版本 >= 18(见 AwesomeExample/package.json 中的engines字段);
  • 按官方要求提前完成 React Native 的 Set Up Your Environment 指南(Android Studio / Xcode 环境);
  • Android 侧建议使用 Android Studio 自带模拟器,iOS 侧使用 Xcode 自带的 iOS Simulator。

2. 安装 JavaScript 依赖

在 AwesomeExample 目录下执行:

npm install

示例工程使用yarn.lock锁定依赖,同样也可以用yarn install。由于react-native-image-crop-picker通过"../"引用仓库根目录,无需单独安装该库。

三、Step 1:启动 Metro 开发服务器

Metro 是 React Native 的 JavaScript 打包与开发服务器。在项目根目录(AwesomeExample)执行:

# Using npm npm start # OR using Yarn yarn start

对应 AwesomeExample/package.json 中的脚本:

"scripts": { "android": "react-native run-android", "ios": "react-native run-ios", "start": "react-native start" }

Metro 启动后保持运行,终端不要关闭。示例工程的 Metro 配置在 AwesomeExample/metro.config.js,它基于@react-native/metro-config的默认配置合并而来,因此无需任何额外配置即可工作。

四、Step 2:构建并运行应用

Metro 运行后,新开一个终端窗口,在项目根目录执行构建命令。

Android

# Using npm npm run android # OR using Yarn yarn android

底层调用react-native run-android。示例工程的 Android 侧开启了一系列值得注意的构建配置(见 AwesomeExample/android/gradle.properties):

  • newArchEnabled=true:开启 React Native 新架构(Fabric + TurboModules);
  • hermesEnabled=true:启用 Hermes JS 引擎;
  • reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64:默认打包四种 CPU 架构。

提示:React Native 新架构要求 react-native-image-crop-picker 版本 >= 0.50.0(见 README.md 的 Important notes)。本示例通过 TurboModule 方式调用原生模块,其原生侧实现位于 android/newArch/java/com/reactnative/ivpusic/imagepicker/PickerModule.java。

iOS

iOS 构建前必须安装 CocoaPods 依赖。首次克隆项目或更新原生依赖后:

bundle install bundle exec pod install

其中bundle install依据 AwesomeExample/Gemfile 安装 Ruby 依赖(对 cocoapods、activesupport、xcodeproj 等版本做了约束);bundle exec pod install依据 AwesomeExample/ios/Podfile 安装 Pod。Podfile 中通过use_react_native!与react_native_post_install完成 React Native 原生依赖的链接,use_native_modules!会自动识别并链接react-native-image-crop-picker(其 iOS 原生代码位于 ios/src)。

之后运行:

# Using npm npm run ios # OR using Yarn yarn ios

如果一切正常,应用会出现在 Android 模拟器、iOS 模拟器或真机上。你也可以直接通过 Android Studio 或 Xcode 打开工程构建运行。

五、Step 3:修改应用与热更新

打开 AwesomeExample/App.tsx 修改代码,保存后应用会自动刷新——这是由 Fast Refresh(快速刷新)机制驱动的,无需重新构建原生代码。

需要强制完整刷新(例如重置应用状态)时:

  • Android:按两次R键,或通过Ctrl+M(Windows/Linux)/Cmd+M(macOS)打开 Dev Menu 选择 "Reload";
  • iOS:在 iOS Simulator 中按R键。

提示:Android 模拟器上打开 Dev Menu 的快捷键为Ctrl+M。

六、示例应用功能全景:App.tsx 逐模块解析

示例 UI 由一组按钮构成,每个按钮对应图片选择器的一种典型用法。下面按功能模块拆解,并标注与 src/NativeImageCropPicker.ts 中 TurboModule 定义(openPicker/openCamera/openCropper/clean/cleanSingle)的对应关系。

1. 相机拍照选图(openCamera)

pickSingleWithCamera(cropping: boolean, mediaType: 'photo' | 'video' = 'photo') { ImagePicker.openCamera({ cropping: cropping, width: 500, height: 500, includeExif: true, mediaType, }) .then(image => { ... }) .catch(e => Alert.alert('Error', e.message)); }

界面上一共有三个按钮使用它:

  • "Select Single Image With Camera":pickSingleWithCamera(false),不裁剪;
  • "Select Single Video With Camera":pickSingleWithCamera(false, 'video'),调用系统相机拍摄视频,mediaType: 'video';
  • "Select Single With Camera With Cropping":pickSingleWithCamera(true),拍照后进入裁剪界面。

这里演示了width/height(裁剪后输出尺寸)与includeExif(返回 EXIF 信息)两个常用参数。

2. 从相册选单张图(openPicker)

pickSingle(cropit: boolean, circular: boolean = false) { ImagePicker.openPicker({ width: 500, height: 500, cropping: cropit, cropperCircleOverlay: circular, sortOrder: 'none', compressImageMaxWidth: 1000, compressImageMaxHeight: 1000, compressImageQuality: 1, compressVideoPreset: 'MediumQuality', includeExif: true, cropperStatusBarLight: true, cropperNavigationBarLight: false, cropperToolbarColor: 'white', cropperActiveWidgetColor: 'white', cropperToolbarWidgetColor: '#3498DB', }) .then(image => { ... }) .catch(e => { ... }); }

对应的两个按钮:

  • "Select Single":pickSingle(false),不裁剪,直接返回原图;
  • "Select Single With Cropping":pickSingle(true),选图后进入裁剪界面;
  • "Select Single With Circular Cropping":pickSingle(true, true),启用cropperCircleOverlay圆形裁剪遮罩(头像裁剪的典型场景)。

这组代码是裁剪 + 压缩 + UI 定制三合一的完整范例:

参数示例值作用
croppingtrue开启裁剪界面
cropperCircleOverlaytrue圆形裁剪遮罩
compressImageMaxWidth/compressImageMaxHeight1000压缩后的最大宽高
compressImageQuality1压缩质量,取值范围 0~1
compressVideoPreset'MediumQuality'iOS 视频压缩预设
sortOrder'none'iOS 相册排序方式
cropperToolbarColor'white'Android 裁剪工具栏颜色
cropperActiveWidgetColor'white'Android 裁剪 ActiveWidget 颜色
cropperToolbarWidgetColor'#3498DB'Android 裁剪工具栏文字/按钮颜色
cropperStatusBarLighttrueAndroid 状态栏浅色模式
cropperNavigationBarLightfalseAndroid 导航栏浅色模式

关于压缩参数,README 给出了补充说明:Android 默认compressImageQuality = 1,iOS 默认0.8;iOS 上取值超过 0.8 对多数图片画质提升不明显,而 0.8 相对 1 可将文件体积降低约一半甚至更多。压缩的底层实现位于 android/src/main/java/com/reactnative/ivpusic/imagepicker/Compression.java,它通过 Bitmap 解码 + 采样率控制实现对输出图片的尺寸与质量双重控制。

3. 返回 Base64(includeBase64)

pickSingleBase64(cropit: boolean) { ImagePicker.openPicker({ width: 300, height: 300, cropping: cropit, includeBase64: true, includeExif: true, }) .then(image => { this.setState({ image: { uri: `data:${image.mime};base64,` + (image as any).data, ... }, }); }) .catch(e => Alert.alert('Error', e.message)); }

对应按钮 "Select Single Returning Base64"。includeBase64: true时,图片文件内容以 base64 字符串形式出现在返回对象的data字段中,可直接拼成data:image/jpeg;base64,...形式的 data URI 作为<Image>的source。README 中的官方用法提示为:

<Image source={{uri: `data:${image.mime};base64,${image.data}`}} />

注意:data字段在 src/NativeImageCropPicker.ts 的类型定义中被标记为可选(data?: string),只有设置了includeBase64才会返回。

4. 仅对已有图片裁剪(openCropper)

cropLast() { if (!this.state.image) { return Alert.alert('No image', 'Before open cropping only, please select image'); } ImagePicker.openCropper({ path: this.state.image.uri, width: 200, height: 200, mediaType: 'photo', }) .then(image => { ... }) .catch(e => { ... }); }

对应按钮 "Crop Last Selected Image"。openCropper与openPicker/openCamera的区别在于:它不再调起相册或相机,而是直接接收一个本地文件路径path,对该图片进行裁剪。这在"先选择后二次裁剪"的业务场景中非常实用。

5. 多选(multiple)

pickMultiple() { ImagePicker.openPicker({ multiple: true, waitAnimationEnd: false, sortOrder: 'desc', includeExif: true, forceJpg: true, }) .then(images => { ... }) .catch(e => Alert.alert('Error', e.message)); }

对应按钮 "Select Multiple"。multiple: true时返回值从单个对象变为数组。README 中给出的最小多选写法为:

ImagePicker.openPicker({ multiple: true }).then(images => console.log(images));

示例还额外演示了waitAnimationEnd: false(iOS 上不等 ViewController 动画结束就 resolve)、sortOrder: 'desc'(iOS 相册按创建时间倒序)、forceJpg: true(iOS 将照片转为 JPG,Live Photo 也会转为 JPG 表示)等 iOS 专属参数。多选时可用minFiles(默认 1)与maxFiles(默认 5)限制文件数量。

6. 临时文件清理(clean / cleanSingle)

cleanupImages() { ImagePicker.clean() .then(() => console.log('removed tmp images from tmp directory')) .catch(e => Alert.alert('Error', e.message)); } cleanupSingleImage() { let image = this.state.image || (this.state.images && this.state.images.length ? this.state.images[0] : null); ImagePicker.cleanSingle(image?.uri || '') .then(() => console.log(`removed tmp image ${image?.uri} from tmp directory`)) .catch(e => Alert.alert('Error', e.message)); }

对应按钮 "Cleanup All Images" 与 "Cleanup Single Image"。README 对此的说明是:库在选取/裁剪过程中会产生临时图片文件,未来会被自动清理;若希望立即释放磁盘空间,可用clean()清理全部临时文件,或用cleanSingle(path)清理单个临时文件。Android 侧的实现位于 android/src/main/java/com/reactnative/ivpusic/imagepicker/ImageCropPicker.java 的cleanSingle(final String pathToDelete, final Promise promise)方法(第 190 行)。

7. 视频渲染与统一资产渲染

renderAsset(image: ImageState) { if (image.mime && image.mime.toLowerCase().indexOf('video/') !== -1) { return this.renderVideo(image); } return this.renderImage(image); }

根据返回对象的mime字段判断是图片还是视频:图片用 RN 内置<Image>渲染,视频用react-native-video的<Video>组件循环播放。这演示了如何根据图片选择器的返回值类型做统一资源展示。

七、响应对象字段说明

无论openPicker、openCamera还是openCropper,resolve 出来的对象结构基本一致,完整定义见 src/NativeImageCropPicker.ts 与 index.d.ts。常用字段:

字段类型说明
pathstring选中文件的本地路径(writeTempFile: false时为 null)
filenamestring文件名
width/heightnumber图片宽高
mimestringMIME 类型(image/jpeg、image/png 等)
sizenumber文件大小(字节)
durationnumber视频时长(毫秒),仅视频有
database64base64 编码的文件内容(需includeBase64)
exifobjectEXIF 信息(需includeExif),格式随平台而异
cropRectobject裁剪矩形{x, y, width, height}
localIdentifierstringiOS 专属,用于 PHAsset 检索
sourceURLstringiOS 专属,源文件路径(无写权限)
creationDate/modificationDatestringiOS 专属,创建/修改时间的 UNIX 时间戳

八、权限配置(运行前必做)

iOS

在 AwesomeExample/ios/AwesomeExample/Info.plist 中,示例已经声明了三个权限描述,这是使用相册/相机/麦克风功能的前置条件:

<key>NSPhotoLibraryUsageDescription</key> <string>Photo Library Access Warning</string> <key>NSCameraUsageDescription</key> <string>Camera usage description</string> <key>NSMicrophoneUsageDescription</key> <string>This app requires to access your microphone to record video ...</string>

在实际业务应用中,你需要把这三个字符串替换为符合自身产品场景的权限说明文案。若只使用部分功能,可按需省略(例如不用相机可去掉NSCameraUsageDescription)。

Android

示例工程在 AwesomeExample/android/app/src/main/AndroidManifest.xml 中声明了:

<uses-feature android:name="android.hardware.camera" android:required="false" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.CAMERA"/>

README 对 Android 权限给出的官方说明是:

  • 若要在项目中使用相机拍照,需添加<uses-permission android:name="android.permission.CAMERA"/>;
  • 若使用前置摄像头,还需添加<uses-feature android:name="android.hardware.camera" android:required="false" />与<uses-feature android:name="android.hardware.camera.front" android:required="false" />(required="false"表示该功能不是应用运行的硬性要求,避免无摄像头设备无法安装)。

库自身的清单 android/src/main/AndroidManifest.xml 会随依赖自动合并,其中包含图片 FileProvider、UCropActivity 以及 Google Play 服务照片选择器模块的声明,通常无需手动处理。

九、常见问题排查

  • 新架构下无法构建:确保使用 react-native-image-crop-picker >= 0.50.0,示例工程通过 TurboModule 方式集成,需保持newArchEnabled=true与库版本匹配。
  • iOS 模拟器无相册/相机:模拟器相册需要先向其中添加照片;相机功能在模拟器上不可用(iOS 错误码E_PICKER_CANNOT_RUN_CAMERA_ON_SIMULATOR,见 index.d.ts),需在真机验证。
  • Android 选视频时不要开启裁剪:README 明确警告,Android 上cropping: true可能导致视频无法显示在相册中,选择视频时应保持cropping为 false。
  • 权限被拒:检查 Info.plist 三个 UsageDescription 是否配置;Android 首次调用相机/相册时需动态授权。
  • 运行报 "Unable to load script" 之类错误:确认 Metro 已在运行,且真机与开发机处于同一网络。

十、进一步学习路径

  • 完整的 API 参数表与全部选项见仓库根 README.md(含 Request Object 与 Response Object 两张完整表格、iOS Smart Album 类型列表);
  • 类型系统与平台专属错误码见 index.d.ts;
  • 原生实现:Android 端 ImageCropPicker.java、Compression.java、ExifExtractor.java;iOS 端 ios/src 下的 ImageCropPicker.mm、Compression.m 等;
  • 单元测试:示例工程带有 App.test.tsx,通过react-test-renderer验证 App 组件可正常渲染,运行npm test(jest)即可执行。

至此,你已经掌握了 AwesomeExample 从环境准备、Metro 启动、双平台构建到各功能模块(拍照、单选、多选、裁剪、圆形裁剪、Base64、二次裁剪、临时文件清理、视频预览)的完整使用链路。接下来不妨直接修改 App.tsx 中的参数(例如将compressImageQuality从 1 调小、开启freeStyleCropEnabled自由裁剪),亲身体验不同配置对输出结果的影响。

  • 移动开发
  • 图像处理

【免费下载链接】react-native-image-crop-picker

iOS/Android image picker with support for camera, video, configurable compression, multiple images and cropping

项目地址:https://gitcode.com/gh_mirrors/re/react-native-image-crop-picker
点击查看免费下载
上一篇:openpilot 响应慢?CAN 总线延迟排查与调优的完整清单
下一篇:戴森球计划工厂蓝图免费库:7000+全流程蓝图,放置即用

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询