You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

react-native-camera拍照后传URI至预览页,Image组件无法显示求助

解决react-native-camera拍摄照片传递URI后无法显示的问题

我之前也碰到过一模一样的情况,别着急,咱们一步步排查解决。首先要明确: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

火山引擎 最新活动