react-native-camera拍照后传URI至预览页,Image组件无法显示求助
我之前也碰到过一模一样的情况,别着急,咱们一步步排查解决。首先要明确:react-native-camera返回的照片URI是本地文件路径,完全不能用require()(它只适用于项目打包时就存在的静态资源),必须用source={{ uri: 你的路径 }},但显示不了通常是这几个核心原因:权限没配置对、URI格式需要调整、或者预览页接收参数时出了问题。
1. 先确认权限配置是否到位
react-native-camera需要相机和存储权限,尤其是Android平台,一定要在AndroidManifest.xml里添加:
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
iOS则要在Info.plist里补充权限说明:
<key>NSCameraUsageDescription</key> <string>需要相机权限来拍摄照片</string> <key>NSPhotoLibraryUsageDescription</key> <string>需要相册权限来保存和查看照片</string>
如果权限没申请,即使拿到URI,系统也会阻止App访问这个文件,自然显示不出来。
2. 检查TakePicture.tsx里的拍照和参数传递逻辑
确保你正确获取了拍照后的URI,并且导航传递参数的方式没问题。比如用React Navigation的话,代码应该是这样的:
// src/containers/TakePicture.tsx import React, { useState, useRef } from 'react'; import { View, Button, Alert } from 'react-native'; import { RNCamera } from 'react-native-camera'; import { useNavigation } from '@react-navigation/native'; const TakePicture = () => { const cameraRef = useRef<RNCamera>(null); const navigation = useNavigation(); const takePicture = async () => { if (cameraRef.current) { const options = { quality: 0.5, base64: false, skipProcessing: false }; const data = await cameraRef.current.takePictureAsync(options); // 先打印URI看看格式,比如Android可能是file:///storage/emulated/0/...,iOS可能是file:///var/mobile/... console.log('拍摄的照片URI:', data.uri); // 导航到预览页,传递URI参数 navigation.navigate('PreviewPhoto', { photoUri: data.uri }); } }; return ( <View style={{ flex: 1 }}> <RNCamera ref={cameraRef} style={{ flex: 1 }} type={RNCamera.Constants.Type.back} /> <Button title="拍摄照片" onPress={takePicture} /> </View> ); }; export default TakePicture;
注意:takePictureAsync返回的data.uri已经是可用的本地路径,不需要额外处理(除非是iOS的旧格式,但新版本react-native-camera会返回正确的file URI)。
3. 修复PreviewPhoto.tsx里的Image组件使用
预览页里必须正确接收参数,并且用uri方式加载,另外Android上有时候需要给Image添加resizeMode,或者明确设置宽高,不然可能显示不出来。代码示例:
// src/containers/PreviewPhoto.tsx import React from 'react'; import { View, Image, StyleSheet } from 'react-native'; import { RouteProp, useRoute } from '@react-navigation/native'; // TypeScript可选:定义导航参数类型,JS可以直接去掉这部分 type RootStackParamList = { PreviewPhoto: { photoUri: string }; }; type PreviewPhotoRouteProp = RouteProp<RootStackParamList, 'PreviewPhoto'>; const PreviewPhoto = () => { const route = useRoute<PreviewPhotoRouteProp>(); const { photoUri } = route.params; // 打印接收的URI,确认和拍照页的一致,排除参数传递错误 console.log('预览页接收的URI:', photoUri); return ( <View style={styles.container}> {/* 关键:用source={{ uri: photoUri }},绝对不要用require */} <Image source={{ uri: photoUri }} style={styles.previewImage} resizeMode="contain" // 这个属性很重要,确保图片适配容器显示 /> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#000', }, previewImage: { flex: 1, width: '100%', height: '100%', }, }); export default PreviewPhoto;
4. 额外排查点(针对Android 10+)
如果是Android 10及以上版本,注意scoped storage的影响。可以在AndroidManifest.xml的<application>标签里添加android:requestLegacyExternalStorage="true"来兼容旧的存储方式:
<application ... android:requestLegacyExternalStorage="true">
按照上面的步骤调整后,应该就能正常显示照片了。我当时就是因为Android权限没配全,加上Image没加resizeMode才踩了坑,调整后立刻就好了。
内容的提问来源于stack exchange,提问作者martins




