Most of the logic when taking photos can be abstracted when using react-native-camera
, so we will focus on using this module in our component and making sure we connect it to our app's state through Redux actions:
/*** src/screens/Camera ***/ import React, { Component } from 'react'; import { Dimensions, StyleSheet, Text, TouchableHighlight, View } from 'react-native'; import { Button, Icon } from 'native-base'; import Camera from 'react-native-camera'; import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; import * as Actions from '../actions'; class CameraScreen extends Component { static navigationOptions = { tabBarIcon: ({ tintColor }) => ( <Icon name='camera' style={{fontSize: 40, color: tintColor}}/> ), }; render() { return ( <View style={styles.container}> <Camera ref={(cam) => { this.camera = cam; }} style={styles.preview} aspect={Camera.constants.Aspect.fill}> <Button onPress={this.takePicture.bind(this)} style={styles.cameraButton} transparent> <Icon name='camera' style={{fontSize: 70, color: 'white'}}/> </Button> </Camera> <Button onPress={() => this.props.navigation.navigate('ImagesList')} style={styles.backButton} transparent> <Icon ios='ios-arrow-dropleft' android='md-arrow-dropleft' style={{fontSize: 30, color: 'white'}}/> </Button> </View> ); } takePicture() { const options = {}; this.camera.capture({metadata: options}) .then((data) => { this.props.addImage(data); this.props.navigation.navigate('ImagesList'); }) .catch(err => console.error(err)); } } const styles = StyleSheet.create({ container: { flex: 1, flexDirection: 'row', }, preview: { flex: 1, justifyContent: 'flex-end', padding: 20 }, capture: { flex: 0, backgroundColor: '#fff', borderRadius: 5, color: '#000', padding: 10, margin: 40 }, cameraButton: { flex: 0, alignSelf: 'center' }, backButton: { position: 'absolute', top:20 } }); function mapStateToProps(state) { return {} } function mapStateActionsToProps(dispatch) { return bindActionCreators(Actions, dispatch) } export default connect(mapStateToProps, mapStateActionsToProps)(CameraScreen);
The way react-native-camera
works is by providing a component we can include in our screen and, through a reference, we can call its capture
method, which returns a promise we can use to call addImage
to upload our image to the app's backend.
Let's take a closer look at the <Camera />
component:
<Camera ref={(cam) => { this.camera = cam; }} style={styles.preview} aspect={Camera.constants.Aspect.fill}> ... </Camera>
The <Camera />
component takes three props:
ref
: This sets a reference to the <Camera />
component in the parent component for it to call the capture method.style
: This allows the developer to specify the look of the component in the app.aspect
: This allows you to define how the view renderer will behave when displaying camera's view. There are three options: fill
, fit
, and stretch
.The takePicture
function will be invoked when the user presses the camera button:
takePicture() { const options = {}; this.camera.capture({metadata: options}) .then((data) => { this.props.addImage(data); this.props.navigation.navigate('ImagesList'); }) .catch(err => console.error(err)); }
We will use the saved reference to the camera to call its capture
method to which we can pass some metadata (for example, the location in which the photo was taken). This method returns a promise, which will be resolved with the image data so we will use this data to call the addImage
action to send this data to the backend, so the picture can be added to the imagesList
. Right after sending the image to the backend, we will make the app navigate back to the ImagesList
screen. The addImage
method will set the addingImages
flag, so the ImageList
screen can display the activity indicator with the corresponding message.
Let's move on to the last screen in our app: MyImages
.
3.134.76.72