Fala Samurai, beleza?
Nós da equipe Dev Samurai temos o prazer de lançar essa nova série de tutoriais sobre React Native chamada React Native Tutorials.
Nessa série, iremos descrever o passo a passo e algumas técnicas para utilizar ferramentas e libs relacionadas a React Native, que foram aprendidas e utilizadas aqui no time de desenvolvimento da Dev Samurai.
Para dar inicio a essa série, vamos falar um pouco sobre como podemos utilizar a câmera do celular com React Native.
Link do Github:https://mautic.devsamurai.com.br/asset/11:tutorial-samuraicam
Índice
Criando o nosso aplicativo
Iremos partir de uma aplicação React Native do zero, gerada pelo:
react-native init SamuraiCam
Para esse tutorial, a ideia é trazer uma tela com 2 botões, 1 para fazer a utilização da câmera para capturar uma foto e outro para excluir a foto tirada que ficará exibida em um pequeno quadrinho.
Essa é uma prévia da aplicação:

De antemão, gostaria de esclarecer que a aplicação gerada no tutorial é um exemplo em que o foco principal é na instalação, configuração e uso de uma lib para React Native que vai auxiliar em acessar a câmera do celular e capturar fotos.
Preparando o Layout
Nosso layout vai ser simples, porém bonito =), e vai nos dar uma base para entender melhor o funcionamento do uso da câmera no React Native.
Vamos utilizar alguns ícones e um logo.
Para os ícones, instalaremos a lib
react-native-vector-icons
e faremos o link para utilizá-la:
yarn add react-native-vector-icons
react-native link react-native-vector-icons
o logo você pode baixar aqui: https://mautic.devsamurai.com.br/asset/10:logotipo-samurai-cam
Agora crie uma pasta chama src na raiz do projeto e dentro dela crie outra pasta chamada assets e dentro dela coloque as imagens do logo.
Arraste o arquivo inicial App.js do aplicativo gerado pelo
react-native init
para dentro da pasta src
Depois para que a mudança de lugar do arquivo principal App.js funcione corretamente, temos que mexer no arquivo index.js na raiz do projeto, altere a linha de código
import App from './App';
para:
import App from './src/App';
Vamos começar a mexer no arquivo App.js adicionando uma
View
com nosso
logo
, os botões
TouchableOpacity
com seus Icons e o quadrinho para visualizar a foto posteriormente:
import React from "react";
import { View, Image, TouchableOpacity, StyleSheet } from "react-native";
import Icon from "react-native-vector-icons/MaterialIcons";
import logo from "./assets/logo.png";
const App = () => {
return (
<View style={styles.container}>
<Image source={logo} style={styles.logo} />
<View style={styles.photo}></View>
<View style={styles.buttons}>
<TouchableOpacity style={styles.button} onPress={() => {}}>
<Icon name="camera-alt" size={40} color={"#f37272"} />
</TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={() => {}}>
<Icon name="delete" size={40} color={"#f37272"} />
</TouchableOpacity>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#f37272"
},
logo: {
alignSelf: "center",
marginTop: 60
},
photo: {
width: 300,
height: 200,
backgroundColor: "#fff",
alignSelf: "center",
marginTop: 80
},
buttons: {
marginTop: 10,
flexDirection: "row",
justifyContent: "center"
},
button: {
backgroundColor: "#fff",
margin: 20,
borderRadius: 150,
width: 80,
height: 80,
alignItems: "center",
justifyContent: "center"
}
});
export default App;
O resultado do app deve estar assim:

Instalando e Configurando a Lib
react-native-camera
do React Native
Para acessar a câmera e capturar fotos vamos utilizar a lib react-native-camera
yarn add react-native-camera
Precisamos realizar alguns passos para configurar a lib e conseguir utiliza lá corretamente.
Primeira coisa é rodar o comando:
react-native link react-native-camera
Configurações para IOS
No arquivo ios/nome_do_projeto/info.plist adicione dentro da tag
<dict>
esse código:
<key>NSCameraUsageDescription</key>
<string>Teste de aplicativo.</string>
Configurações para Android
No arquivo android/app/build.gradle encontre a parte que tem as configurações default do android chamada
defaultConfig
e adicione a linha
missingDimensionStrategy 'react-native-camera', 'general'
, seu código deve ficar parecido com esse:
defaultConfig {
applicationId "com.reactnativecameraexample"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
missingDimensionStrategy 'react-native-camera', 'general'
}
Depois vá até o arquivo android/app/src/main/AndroidManifest.xml e adicione essa linha:
<uses-permission android:name="android.permission.CAMERA" />
Utilizando a câmera
Com a estrutura do Layout pronta e a lib
react-native-camera
configurada, podemos prosseguir para utilizar a câmera.
Para isso nós iremos criar agora nosso componente
Camera
.
Primeiro vamos importar o componente
RNCamera
da lib
react-native-camera
para utilizar dentro de um
Modal
import { RNCamera } from "react-native-camera";
O
Modal
é um componente do React Native que fica como se fosse empilhado acima do componente anterior, então vamos controlar a visibilidade desse modal com o valor de
isCameraVisible
no
state
do componente App:
import React, { useState } from "react";
import { Modal, View, Image, TouchableOpacity, StyleSheet } from "react-native";
import Icon from "react-native-vector-icons/MaterialIcons";
import { RNCamera } from "react-native-camera";
import logo from "./assets/logo.png";
const Camera = ({ isVisible, onChangePhoto, onCloseCamera }) => {
const [camera, setCamera] = useState();
return (
<Modal animationType="slide" transparent={false} visible={isVisible}>
<RNCamera
ref={ref => setCamera(ref)}
style={{ flex: 1 }}
type={RNCamera.Constants.Type.back}
autoFocus={RNCamera.Constants.AutoFocus.on}
flashMode={RNCamera.Constants.FlashMode.off}
androidCameraPermissionOptions={{
title: "Permissão para usar a câmera",
message: "Precisamos da sua permissão para usar a câmera.",
buttonPositive: "Ok",
buttonNegative: "Cancelar"
}}
captureAudio={false}
>
<Icon
name="photo-camera"
size={40}
color={"#fff"}
onPress={() => {}}
style={styles.buttonTakePicture}
/>
<Icon
name="close"
size={50}
color={"#fff"}
onPress={onCloseCamera}
style={styles.buttonCloseCamera}
/>
</RNCamera>
</Modal>
);
};
const App = () => {
const [isCameraVisible, setIsCameraVisible] = useState(false);
const onCloseCamera = () => {
setIsCameraVisible(false);
};
return (
<View style={styles.container}>
<Image source={logo} style={styles.logo} />
<View style={styles.photo}></View>
<View style={styles.buttons}>
<TouchableOpacity
style={styles.button}
onPress={() => {
setIsCameraVisible(true);
}}
>
<Icon name="camera-alt" size={40} color={"#f37272"} />
</TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={() => {}}>
<Icon name="delete" size={40} color={"#f37272"} />
</TouchableOpacity>
</View>
<Camera isVisible={isCameraVisible} onCloseCamera={onCloseCamera} />
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#f37272"
},
logo: {
alignSelf: "center",
marginTop: 60
},
photo: {
width: 300,
height: 200,
backgroundColor: "#fff",
alignSelf: "center",
marginTop: 80
},
buttons: {
marginTop: 10,
flexDirection: "row",
justifyContent: "center"
},
button: {
backgroundColor: "#fff",
margin: 20,
borderRadius: 150,
width: 80,
height: 80,
alignItems: "center",
justifyContent: "center"
},
buttonTakePicture: {
flex: 0,
alignSelf: "center",
position: "absolute",
bottom: 20
},
buttonCloseCamera: {
flex: 0,
position: "absolute",
top: 20,
right: 20
}
});
export default App;
Ao clicar no botão para exibir a câmera então:

Perceba que definimos um valor no
state
do componente
Camera
para usar como referência para o componente
RNCamera
.
No
RNCamera
pudemos notar algumas configurações:
-
type
: Tipo da câmera (front/back) -
autoFocus
: Uso o foco da câmera automaticamente. -
flashMode
: Uso do flash. -
androidCameraPermissionOptions
: Configuração da caixinha de mensagem para pedir permissão de uso da câmera do celular. -
captureAudio
: Captura de áudio (usado em gravações de video).
Agora precisamos implementar a função que vai capturar a foto, vamos chamá-lo de
onTakePicture
e ele irá usar a valor de
camera
que está referenciando o
RNCamera
chamando o método
takePictureAsync
.
Essa função irá chamar o método
takePictureAsync
e colocar o valor dele que no caso é a foto capturada em um valor
photo
que vamos declarar lá no componente App para poder usar no quadrinho de foto.
Fica assim então:
import React, { useState } from "react";
import {
Alert,
Modal,
View,
Image,
TouchableOpacity,
StyleSheet
} from "react-native";
import Icon from "react-native-vector-icons/MaterialIcons";
import { RNCamera } from "react-native-camera";
import logo from "./assets/logo.png";
const Camera = ({ isVisible, onChangePhoto, onCloseCamera }) => {
const [camera, setCamera] = useState();
const onTakePicture = async () => {
try {
const { uri } = await camera.takePictureAsync({
quality: 0.5,
forceUpOrientation: true,
fixOrientation: true,
skipProcessing: true
});
onChangePhoto(uri);
} catch (error) {
Alert.alert("Erro", "Houve um erro ao tirar a foto.");
}
};
return (
<Modal animationType="slide" transparent={false} visible={isVisible}>
<RNCamera
ref={ref => setCamera(ref)}
style={{ flex: 1 }}
type={RNCamera.Constants.Type.back}
autoFocus={RNCamera.Constants.AutoFocus.on}
flashMode={RNCamera.Constants.FlashMode.off}
androidCameraPermissionOptions={{
title: "Permissão para usar a câmera",
message: "Precisamos da sua permissão para usar a câmera.",
buttonPositive: "Ok",
buttonNegative: "Cancelar"
}}
captureAudio={false}
>
<Icon
name="photo-camera"
size={40}
color={"#fff"}
onPress={onTakePicture}
style={styles.buttonTakePicture}
/>
<Icon
name="close"
size={50}
color={"#fff"}
onPress={onCloseCamera}
style={styles.buttonCloseCamera}
/>
</RNCamera>
</Modal>
);
};
const App = () => {
const [isCameraVisible, setIsCameraVisible] = useState(false);
const [photo, setPhoto] = useState(null);
const onChangePhoto = newPhoto => {
setPhoto(newPhoto);
setIsCameraVisible(false);
};
const onCloseCamera = () => {
setIsCameraVisible(false);
};
return (
<View style={styles.container}>
<Image source={logo} style={styles.logo} />
<View style={styles.photo}></View>
<View style={styles.buttons}>
<TouchableOpacity
style={styles.button}
onPress={() => {
setIsCameraVisible(true);
}}
>
<Icon name="camera-alt" size={40} color={"#f37272"} />
</TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={() => {}}>
<Icon name="delete" size={40} color={"#f37272"} />
</TouchableOpacity>
</View>
<Camera
isVisible={isCameraVisible}
onChangePhoto={onChangePhoto}
onCloseCamera={onCloseCamera}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#f37272"
},
logo: {
alignSelf: "center",
marginTop: 60
},
photo: {
width: 300,
height: 200,
backgroundColor: "#fff",
alignSelf: "center",
marginTop: 80
},
buttons: {
marginTop: 10,
flexDirection: "row",
justifyContent: "center"
},
button: {
backgroundColor: "#fff",
margin: 20,
borderRadius: 150,
width: 80,
height: 80,
alignItems: "center",
justifyContent: "center"
},
buttonTakePicture: {
flex: 0,
alignSelf: "center",
position: "absolute",
bottom: 20
},
buttonCloseCamera: {
flex: 0,
position: "absolute",
top: 20,
right: 20
}
});
export default App;
O método
onChangePhoto
está atualizando o estado de
photo
com a foto capturada pela câmera e setada la no componente
Camera
.
Assim o valor de
photo
é a foto atual capturada, com isso, podemos exibir ela no nosso componente quadrinho.
Para isso vamos atualizar o componente
ImageBackground
para exibir a foto, esse componente é importado da API do React Native da mesma forma que o
Text
,
View
, etc.
E para o botão de deletar a imagem, só precisamos setar o valor de
photo
para
null
assim limpamos o quadrinho.
O código final, fica assim então:
import React, { useState } from "react";
import {
Alert,
Modal,
View,
Image,
ImageBackground,
TouchableOpacity,
StyleSheet
} from "react-native";
import Icon from "react-native-vector-icons/MaterialIcons";
import { RNCamera } from "react-native-camera";
import logo from "./assets/logo.png";
const Camera = ({ isVisible, onChangePhoto, onCloseCamera }) => {
const [camera, setCamera] = useState();
const onTakePicture = async () => {
try {
const { uri } = await camera.takePictureAsync({
quality: 0.5,
forceUpOrientation: true,
fixOrientation: true,
skipProcessing: true
});
onChangePhoto(uri);
} catch (error) {
Alert.alert("Erro", "Houve um erro ao tirar a foto.");
}
};
return (
<Modal animationType="slide" transparent={false} visible={isVisible}>
<RNCamera
ref={ref => setCamera(ref)}
style={{ flex: 1 }}
type={RNCamera.Constants.Type.back}
autoFocus={RNCamera.Constants.AutoFocus.on}
flashMode={RNCamera.Constants.FlashMode.off}
androidCameraPermissionOptions={{
title: "Permissão para usar a câmera",
message: "Precisamos da sua permissão para usar a câmera.",
buttonPositive: "Ok",
buttonNegative: "Cancelar"
}}
captureAudio={false}
>
<Icon
name="photo-camera"
size={40}
color={"#fff"}
onPress={onTakePicture}
style={styles.buttonTakePicture}
/>
<Icon
name="close"
size={50}
color={"#fff"}
onPress={onCloseCamera}
style={styles.buttonCloseCamera}
/>
</RNCamera>
</Modal>
);
};
const App = () => {
const [isCameraVisible, setIsCameraVisible] = useState(false);
const [photo, setPhoto] = useState(null);
const onChangePhoto = newPhoto => {
setPhoto(newPhoto);
setIsCameraVisible(false);
};
const onCloseCamera = () => {
setIsCameraVisible(false);
};
return (
<View style={styles.container}>
<Image source={logo} style={styles.logo} />
<View style={styles.photo}>
<ImageBackground
style={{ width: "100%", height: "100%" }}
source={{ uri: photo }}
/>
</View>
<View style={styles.buttons}>
<TouchableOpacity
style={styles.button}
onPress={() => {
setIsCameraVisible(true);
}}
>
<Icon name="camera-alt" size={40} color={"#f37272"} />
</TouchableOpacity>
<TouchableOpacity
style={styles.button}
onPress={() => {
setPhoto(null);
}}
>
<Icon name="delete" size={40} color={"#f37272"} />
</TouchableOpacity>
</View>
<Camera
isVisible={isCameraVisible}
onChangePhoto={onChangePhoto}
onCloseCamera={onCloseCamera}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#f37272"
},
logo: {
alignSelf: "center",
marginTop: 60
},
photo: {
width: 300,
height: 200,
backgroundColor: "#fff",
alignSelf: "center",
marginTop: 80
},
buttons: {
marginTop: 10,
flexDirection: "row",
justifyContent: "center"
},
button: {
backgroundColor: "#fff",
margin: 20,
borderRadius: 150,
width: 80,
height: 80,
alignItems: "center",
justifyContent: "center"
},
buttonTakePicture: {
flex: 0,
alignSelf: "center",
position: "absolute",
bottom: 20
},
buttonCloseCamera: {
flex: 0,
position: "absolute",
top: 20,
right: 20
}
});
export default App;
Conclusão
Utilizar a câmera do celular é uma tarefa bastante comum e requisitada para os desenvolvedores de aplicativos. Então aqui pudemos ter uma base de como fazer isso em React Native, utilizando um exemplo bem simples.
Agora deixa agente saber o que acho do conteúdo, por isso deixa aqui seu comentário, suas dúvidas e se deseja que façamos um exemplo mais elaborado como uma parte 2 desse tutorial onde poderemos incrementar a aplicação para gravar as fotos na pasta de imagens e acessar depois para listar a imagens capturadas, etc.
Não deixe de participar da nossa comunidade no Discord, lá podemos discutir sobre diversos assuntos relacionados a programação e os cursos do Dev Samurai, você vai poder encontrar com o pessoal da equipe Dev Samurai e também toda comunidade que participa e esta engajada em aprender a fazer aplicativos e discutir sobre programação, então segue o link:
Comunidade Dev Samurai no Discord.
Segue o link do repositório para você baixar o código:https://mautic.devsamurai.com.br/asset/11:tutorial-samuraicam
Valeu e até a próxima!