Як створити додаток для камери за допомогою Expo та React Native

Якщо ви не знайомі з expo, це клієнт, який допоможе вам створювати програми React Native з меншою складністю збірки. Це також допоможе вам подолати стрес від встановлення та налаштування вашого середовища для запуску React Native.

У цьому підручнику ми створимо простий додаток для камери, в якому користувач може робити фотографії, переглядати попередні перегляди своїх фотографій, використовувати режим спалаху та перемикатися між передньою та задньою камерами.

Передумови

Expo не вимагає багато для того, щоб почати створювати свій перший додаток React Native. Ви можете дізнатись більше про встановлення expo та expo-cli тут, у документації.

Примітка: у цьому підручнику я буду використовувати macOS та iOS. Ви також можете використовувати Android, на даний момент немає великої різниці при використанні експо.

Ви можете встановити expo та expo-cli глобально, виконавши таку команду:

npm install --global expo-cli

Для запуску Expo потрібен Nodejs. Ви можете запустити останню версію на офіційному веб-сайті тут.

Починаємо

Після встановлення Expo та Nodejs ви можете розпочати завантаження нового проекту Expo за допомогою команди нижче:

expo init expo-camera-app

Як встановити пакунки та запустити програму

Expo надає нам клієнтський додаток, де ми можемо запустити і переглянути попередній перегляд програми, яку ми створюємо. Його можна завантажити як в App Store, так і в Google Play.

Це інтерфейс програми.

Як розпочати виставковий проект

Зайдіть в каталог додатків і запустіть додаток.

cd expo-camera-app 

Вам буде запропоновано кілька запитань, щоб вибрати шаблон програми за замовчуванням. У цьому посібнику ми просто обираємо порожній варіант (TypeScript), але знову ж таки ви можете вибрати те, що підходить саме вам.

Запустіть програму

Після завантаження проекту ми можемо запустити програму за допомогою expo run

Це відкриє вікно у вашому браузері, де ви можете переглянути журнали. Він також створить QR-код, який ви зможете відсканувати для запуску програми на своєму пристрої.

Хороша річ у expo полягає в тому, що вам не потрібно встановлювати та налаштовувати симулятори для запуску програми. Це все ще дає вам можливість запускати expo на тренажері, але вам доведеться встановити та налаштувати симулятор самостійно.

Поверніться до нашого додатку. Якщо припустити, що ви успішно запустили програму на пристрої, це буде екран за замовчуванням:

Відкрийте каталог додатків у вашому улюбленому редакторі коду. Я використовую код VS.

Вигляд App.tsxбуде виглядати так:

import {StatusBar} from 'expo-status-bar' import React from 'react' import {StyleSheet, Text, View} from 'react-native' export default function App() { return (  Open up App.tsx to start working on your app!   ) } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center' } }) 

Як створити інтерфейс користувача

Після запуску проекту настав час розпочати створення інтерфейсу.

Встановіть експо-камеру

Наступним кроком є ​​встановлення експо-камери, наприклад:

expo install expo-camera

Ми створимо простий інтерфейс, який дозволить користувачеві розпочати процес використання камери.

import {StatusBar} from 'expo-status-bar' import React from 'react' import {StyleSheet, Text, View, TouchableOpacity} from 'react-native' export default function App() { return (     Take picture      ) } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center' } }) 

Це простий користувальницький інтерфейс: ми імпортуємо TouchableOpacityдля кнопки та робимо кілька простих стилів. Якщо вам цікаво, як стиль працює в React Native, ви можете переглянути дві мої статті тут:

  • Стиль у React Native
  • Демістифікація Flexbox у React Native

Тепер ми повинні використовувати useStateгачок для управління станом та відображення вигляду камери, коли користувач натискає кнопку зробити знімок .

   Take picture  
 const [startCamera,setStartCamera] = React.useState(false) const __startCamera = ()=>{ }

Коли користувач натискає кнопку, нам потрібно зробити дві важливі речі:

  • Попросіть дозволу отримати доступ до камери. При розробці мобільних пристроїв доступ до багатьох власних API та мобільних функцій часто обмежується дозволами користувача та конфіденційністю. Це просто те, до чого потрібно звикнути при розробці мобільних додатків.
  • Change the state and present the camera.

Let's import the camera module from expo-camera with this command:

import {Camera} from 'expo-camera'

And add the camera view, like this:

  { camera = r }} >

We can use ref to access the camera's methods:

let camera: Camera

When the take picture button is pressed the __startCamera function will be called:

 const __startCamera = async () => { const {status} = await Camera.requestPermissionsAsync() if(status === 'granted'){ // do something }else{ Alert.alert("Access denied") }

The function will ask for permission first. If the user grant access to the camera, we can proceed and open the camera. If not, we show a simple alert.

Add the camera component

Let's display the camera when the user grants access to the device's camera.

 const __startCamera = async () => { const {status} = await Camera.requestPermissionsAsync() if (status === 'granted') { // start the camera setStartCamera(true) } else { Alert.alert('Access denied') } }

We have to make some changes to the UI and add a conditional rendering. We display the camera only when the user requests it, otherwise we display the default screen.

 {startCamera ? (  { camera = r }} > ) : (    Take picture    )}

Cool, now we need to add a button so we can take the actual picture.

Add the capture button

This is a simple View inside the camera view that has an absolute position. So we make sure that it is always on the top of the camera.

How to take a picture

The app should take a picture when capture button is pressed. That function will look like the below:

 const __takePicture = async () => { if (!camera) return const photo = await camera.takePictureAsync() }

First, we check that we have access to the Camera component using ref:

 if (!camera) return // if the camera is undefined or null, we stop the function execution

Then we take the picture by calling the takePictureAsync method. It returns a promise and an object that contains the picture's details. The result will look like this:

Object { "height": 4224, "uri": "file:///var/mobile/Containers/Data/Application/E6740A15-93AF-4120-BF11-6E8B74AFBF93/Library/Caches/ExponentExperienceData/%2540anonymous%252Fcamera-app-ee0fa3c8-1bb1-4d62-9863-33bf26341c55/Camera/19F0C5DD-7CA6-4043-8D89-AF65A1055C7E.jpg", "width": 1952, }

We are only interested in the Picture URL uri. After we take a picture, we have to show the photo preview and hide the camera view. To do that we will use two hooks to change the state:

 const [previewVisible, setPreviewVisible] = useState(false) const [capturedImage, setCapturedImage] = useState(null)
 const __takePicture = async () => { if (!camera) return const photo = await camera.takePictureAsync() console.log(photo) setPreviewVisible(true) setCapturedImage(photo) }
  • setPreviewVisible to show the preview
  • setCapturedImage(photo) to store the object result

Then we display the preview like this:

 {previewVisible && capturedImage ? (  ) : (  { camera = r }} >         )}

The CameraPreview component looks like this:

const CameraPreview = ({photo}: any) => { console.log('sdsfds', photo) return (    ) }

And the result looks like this:

How to re-take a picture

We can add some buttons to the preview that will allow the user to perform more actions. For example, they could re-take the photo or save it.

Add the savePhoto and retakePicture props to the CameraPreview component like this:

When the Re-take button is pressed, we will have to hide the preview, remove the current picture, and show the camera again. Do that with the following code:

 const __retakePicture = () => { setCapturedImage(null) setPreviewVisible(false) __startCamera() }

How to add other options – back camera, flash, and more

expo-camra offers many options for customizing the camera, like FlashMode, setting the Camera type (front/back), zooming, and so on.

How to add FlashMode

Let's add an option so the user can turn FlashMode on and off:

We simply create a small button to switch off/on the flash, like this:

   ⚡️  

And we just change the state when the button is pressed:

 const [flashMode, setFlashMode] = React.useState('off') const __handleFlashMode = () => { if (flashMode === 'on') { setFlashMode('off') } else if (flashMode === 'off') { setFlashMode('on') } else { setFlashMode('auto') } }

And then we add FlashMode props:

  { camera = r }} >

How to access the front and the back camera

We will add a button that switches between the back and front camera.

We can get the default camera type directly from the camera module like below:

 const [cameraType, setCameraType] = React.useState(Camera.Constants.Type.back)

Add type props like this:

  { camera = r }} >

And add the switch button:

  {cameraType === 'front' ? '?' : '?'}  

And switch function:

 const __switchCamera = () => { if (cameraType === 'back') { setCameraType('front') } else { setCameraType('back') } }

Here is the result:

You can find the full source code on GitHub.

Wrapping up

In general, Expo is an amazing tool that can save you a lot of time. It helps you start building directly and saves you the pain of environment setup.

Іноді вам може знадобитися створити власне розширення та по-своєму обробляти використання рідних функцій. У цьому випадку я рекомендую використовувати CLI для реагування, щоб ви могли легко модифікувати та грати з рідним кодом.

Привіт, мене звати Саїд Хаяні. Я створив subscribi.io, щоб допомогти творцям, блогерам та інфлюенсерам збільшити свою аудиторію за допомогою бюлетеня.

Приєднуйтесь до мого списку розсилки, якщо вам цікаво прочитати більше про React Native.