1

I have just started using React Native with Expo so I am kind of confused. So, I have made a camera component which I imported in the main screen. Everything looks good. But I can't take pictures. I cannot click the snap icon and save the image. Is there a component that I missed? I have only posted the CameraComponent function below.

CameraScreen.js

const CameraScreen = () => {


    const [hasPermission, setHasPermission] = useState(null);
    const [type, setType] = useState(Camera.Constants.Type.back);

    useEffect(() => {
        (async () => {
            const { status } = await Camera.requestCameraPermissionsAsync();
            setHasPermission(status === 'granted');
        })();
    }, []);

    if (hasPermission === null) {
        return <View />;
    }
    if (hasPermission === false) {
        return <Text>No access to camera</Text>;
    }

    const takePicture = () => {
        if (Camera) {
            Camera.takePictureAsync({ onPictureSaved: onPictureSaved });
        }
    };

    const onPictureSaved = photo => {
        console.log(photo);
    }

    return (

        <View style={styles.container}>
            <Camera style={styles.camera}
                type={type}
                ref={(r) => {
                    camera = r
                }}>
                <View style={styles.buttonContainer}>
                    <View style={styles.flip}>
                        <TouchableOpacity
                            style={styles.button}
                            onPress={() => {
                                setType(
                                    type === Camera.Constants.Type.back
                                        ? Camera.Constants.Type.front
                                        : Camera.Constants.Type.back
                                );
                            }}
                        >
                            <Text style={styles.text}> Flip </Text>
                        </TouchableOpacity>
                    </View>

                    <View style={styles.Shot}>
                        <TouchableOpacity style={styles.button} onPress={takePicture}>
                            <Text style={styles.text}> Shot </Text>
                        </TouchableOpacity>
                    </View>
                </View>
            </Camera>
        </View>
    );
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
    },
    camera: {
        flex: 1,
        justifyContent: 'flex-end',
        paddingBottom: 25,
        paddingLeft: 10,
        paddingRight: 10
    },
    flip:{ 
    },
    Shot:{
    },
    buttonContainer: {
        flexDirection: 'row',
        backgroundColor: 'transparent',
        justifyContent: 'space-between',
        alignItems: 'flex-end',
    },
    text: {
        fontSize: 25,
        color: 'white',
    },
});

export default CameraScreen

The button(Shot) in the bottom should automatically take and save image.

박종준
  • 125
  • 1
  • 2
  • 10

2 Answers2

0

Instead of

Camera.takePictureAsync({ onPictureSaved: onPictureSaved });

A callback invoked when picture is saved. If set, the promise of this method will resolve immediately with no data after picture is captured. The data that it should contain will be passed to this callback. If displaying or processing a captured photo right after taking it is not your case, this callback lets you skip waiting for it to be saved.

You should use the async promise from takePictureAsync function

Camera.takePictureAsync()
    .then(onPictureSaved);


//your onPictureSaved function
const onPictureSaved = ({ uri, width, height, exif, base64 }) => {
    console.log(uri);
}

Ngima Sherpa
  • 1,397
  • 1
  • 13
  • 34
0

In the latest version (~13.2.1) of expo-camera, you need to use useRef inside functional components.

Firstly, create a ref named cameraRef.

const cameraRef = useRef(null);

Then, create your Camera component with TouchableOpacity inside.

    <Camera type={CameraType.back} ref={cameraRef}>
      <View>
        <TouchableOpacity
          onPress={async () => {
            if (cameraRef.current) {
              let photo = await cameraRef.current.takePictureAsync();
              console.log(photo.uri);
            }
          }}
        >
     </View>
   </Camera>

Now, you are ready to take photographs!

And, an additional information, if any error happens related to your first shoot attempt, there is a warning in the documentation of expo-camera:

Make sure to wait for the onCameraReady callback before calling this method.

rch
  • 127
  • 1
  • 7