앱의 카메라로 찍은 사진을 사용하고 싶지만, 카메라 자체의 세부적인 설정까지 하기 어려울때!!
기본카메라로 찍은 사진만 사용해도 괜찮을 때 쓰면 간편한 라이브러리를 소개한다.
- 설치 환경 : expo
* 만약 bare라던가 날것의 react-native라면 추가적인 설정이 필요하다. 공식 문서에 있다
참고 : https://github.com/expo/expo/tree/sdk-47/packages/expo-image-picker
1. 설치
npx expo install expo-image-picker
위의 명령어로 설치를 해준다음 app.json 파일에 설정을 추가로 해줘야한다.
{
"expo": {
"plugins": [
[
"expo-image-picker",
{
"cameraPermission": "Spot 등록을 위해 카메라 접근권한을 허용해주세요.",
"photosPermission": "Spot 등록을 위해 앨범 접근권한을 허용해주세요"
}
]
]
}
}
플러그 인부분만 복붙하면 된다. 혹시 어디에 할지 모르는 사람을 위해
<app.json 전문>
이렇게 붙여 넣으면 된다!
+ 기본적으로 photosPermission (사진 사용권한, 앨범에 있는 사진 올리기) 을 요청하는데 나는 카메라 사용자체도 요청할 것이기 때문에
수정해주었다. 공식문서에 보면 나와있다!
2. ImagePicker.js 만들어주기
설치를 해준다음 이 플러그인을 사용하기 위해 따로 js 파일도 생성해줘야한다.
사진선택 버튼과 해당 버튼을 눌렀을 때, 권한을 요청하는 함수를 설정해줘야한다.
import { Alert, Button, Image, StyleSheet, Text, View } from 'react-native';
import {
launchCameraAsync,
useCameraPermissions,
PermissionStatus,
requestMediaLibraryPermissionsAsync,
useMediaLibraryPermissions,
launchImageLibraryAsync,
MediaTypeOptions,
} from 'expo-image-picker';
import { useState } from 'react';
function ImagePicker({userPickImage}) {
const [pickedImage, setPickedImage] = useState();
const [cameraPermissionInformation, requestPermission] = useCameraPermissions();
const [albumPermissionInfomation, requestAlbumPermission] = useMediaLibraryPermissions();
// 카메라 접근 권한요청
async function verifyPermissions() {
if (cameraPermissionInformation.status === PermissionStatus.UNDETERMINED) {
const permissionResponse = await requestPermission();
return permissionResponse.granted;
}
if (cameraPermissionInformation.status === PermissionStatus.DENIED) {
Alert.alert(
'권한이 필요합니다!',
'Spot을 등록하려면 카메라 접근권한이 필요합니다..'
);
return false;
}
return true;
}
// 앨범 접근권한 요청
async function albumVerifyPermissions(){
if(albumPermissionInfomation.status === PermissionStatus.UNDETERMINED){
const permissionResponse = await requestAlbumPermission();
return permissionResponse.granted;
}
if(albumPermissionInfomation.status === PermissionStatus.DENIED){
Alert.alert('권한이 필요합니다!', 'spot을 등록하려면 사진 접근권한이 필요합니다.');
return false;
}
return true;
}
// 카메라로 사진 이미지 사용관련
async function takeImageHandler() {
const hasPermission = await verifyPermissions();
if (!hasPermission) {
return;
}
const image = await launchCameraAsync({
allowsEditing: true, // 사진자르기 허용
aspect: [16, 9], // 사진품질설정
quality: 0.5,
});
setPickedImage(image.uri);
userPickImage(image.uri);
}
// 앨범 이미지 사용 관련
async function albumImageHandler(){
const hasPermission = await albumVerifyPermissions();
if(!hasPermission){
return;
}
const image = await launchImageLibraryAsync({
mediaTypes: MediaTypeOptions.Images, // 사진만 허용
allowsEditing: true,
aspect: [16, 9], // 사진 비율 설정
quality: 1, // 용량
});
setPickedImage(image.uri);
userPickImage(image.uri);
}
let imagePreview = <Text>No image taken yet.</Text>;
if (pickedImage) {
imagePreview = <Image style={styles.image} source={{ uri: pickedImage }} />;
}
return (
<View>
<View style={styles.imagePreview}>{imagePreview}</View>
<View style={styles.buttonContainer}>
<Button title="Camera" onPress={takeImageHandler} />
<Button title="앨범에서 가져오기" onPress={albumImageHandler} />
</View>
</View>
);
}
export default ImagePicker;
const styles = StyleSheet.create({
imagePreview: {
width: '100%',
height: 200,
marginVertical: 8,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'white',
borderRadius: 4,
},
image: {
width: '100%',
height: '100%',
},
buttonContainer:{
justifyContent: 'space-evenly',
alignItems:'center',
flexDirection:'row',
marginVertical: 7,
marginHorizontal: 5,
}
});
조금 길지만 중요부분에 주석을 써놨으니 알아보기 어렵지 않을 것이다.
그리고 이렇게 다른 컴포넌트를 사용하는 것처럼 import해서 사용하면 끝이다!
혹시 몰라서 내가 사용한 곳의 코드도 전문 첨부해둔다.
<사용한 곳 전문>
// 스팟 등록할 때 입력사항들
import { View, Text, TextInput, ScrollView } from "react-native";
import { useCallback, useState } from 'react';
import ImagePicker from './ImagePicker';
import { StyleSheet } from 'react-native';
import LocationPicker from './LocationPicker';
import Button from './../ui/Button';
import { Spot } from '../../models/spot';
// 스팟 등록할 때
function SpotForm({createSpotHandler}){
const [enteredTitle, setEnteredTitle] = useState('');
const [pickedImage, setPickedImage] = useState();
const [pickedLocation, setPickedLocation] = useState();
const [enteredDescription, setEnteredDescription] = useState();
function changeTitleHandler(enteredText){
setEnteredTitle(enteredText)
}
function pickedImageHandler(imageURL){
setPickedImage(imageURL);
}
function describtionHandler(enteredDescription){
setEnteredDescription(enteredDescription);
}
const pickedLocationHandler = useCallback((location) => {
setPickedLocation(location);
},[]);
function savePlaceHandler(){
console.log(enteredTitle);
console.log(pickedImage);
console.log(pickedLocation); // 정상적으로 다 들어옴
//constructor(title, imgURL, address, location, description) 정의한대로 데이터 모으기
const spotData = new Spot(enteredTitle, pickedImage, pickedLocation, enteredDescription);
// addSpot.js에 있음
createSpotHandler(spotData);
}
return(
<ScrollView >
<View style={styles.form}>
<View>
<Text style={styles.label}>Spot 명</Text>
<TextInput style={styles.input} onChangeText={changeTitleHandler} value={enteredTitle} />
</View>
<ImagePicker userPickImage={pickedImageHandler}/>
<LocationPicker userPickLocation={pickedLocationHandler}/>
<Text style={styles.label}>Spot 설명</Text>
<TextInput style={styles.input} onChangeText={describtionHandler} value={enteredDescription}></TextInput>
<Button onPress={savePlaceHandler}>Spot 등록</Button>
</View>
</ScrollView>
)
}
export default SpotForm;
const styles = StyleSheet.create({
form:{
flex: 1,
padding:24,
},
label:{
fontWeight: 'bold',
marginBottom: 4,
color: '#ffff'
},
input:{
marginVertical: 8,
paddingHorizontal: 4,
paddingVertical: 8,
fontSize: 16,
borderBottomColor: 'blue',
borderBottomWidth:2,
backgroundColor: 'green',
}
})
728x90
'React & React-native' 카테고리의 다른 글
[ React ] react 생명주기란? - 생명주기 함수들 (0) | 2023.06.26 |
---|---|
<google-map-api> 어플에 지도 띄우기 (0) | 2022.12.16 |
<React-native> React-native Cli 환경에서 앱 만들기 (0) | 2022.12.12 |
<React-native> bare workflow 환경에서 앱 만들기 - 1 (0) | 2022.12.12 |
<React> 클래스형과 함수형 컴포넌트의 차이? (0) | 2022.12.07 |