업로드할 사진 선택 또는 카메라 촬영하기
리액트 네이티브 앱에서 버튼을 클릭했을 때 업로드하라 사진을 갤러리에서 선택할지 아니면 카메라로 새로 촬영할지 사용자가 선택하도록 모달을 띄어보려고 한다.
ActionSheetIOS는 이름에서 유추할 수 있듯이 iOS에서만 지원되는 API로, 지금과 같이 사용자에게 선택지를 줄 때 iOS에서 주로 사용하는 UI다.
안드로이드의 경우에는 모달을 통해 선택할 수 있도록 구현하는데, 만약 안드로이드에서도 ActionSheetIOS와 같은 UI로 기능을 구현하고 싶다면 @expo/react-native-action-sheet를 사용하면 된다.
1. 모달 만들기
리액트 네이티브에서 모달을 만들 때는 주로 Modal이라는 컴포넌트를 사용한다.
이 컴포넌트를 사용하지 않아도 직접 구현할 수 있지만, 이 컴포넌트를 사용하면 더욱 간편하게 모달을 구현할 수 있다.
import React from "react";
import { StyleSheet, Modal, View, Pressable, Text } from "react-native";
import Icon from "react-native-vector-icons/MaterialIcons";
function UploadModeModal({visible, onClose, onLaunchCamera, onLaunchImageLibrary}) {
return (
<Modal
visible={visible}
transparent={true}
animationType="fade"
onRequestClose={onClose} >
<Pressable style={styles.background} onPress={onClose}>
<View style={styles.whiteBox}>
<Pressable
style={styles.actionButton}
android_ripple={{color: "#eee"}}
onPress={() => {
onLaunchCamera();
onClose();
}} >
<Icon name="camera-alt" color="#757575" size={24} style={styles.icon} />
<Text style={styles.actionText}>카메라로 촬영하기</Text>
</Pressable>
<Pressable
style={styles.actionButton}
android_ripple={{color: "#eee"}}
onPress={() => {
onLaunchImageLibrary();
onClose();
}} >
<Icon name="photo" color="#757575" size={24} style={styles.icon} />
<Text style={styles.actionText}>사진 선택하기</Text>
</Pressable>
</View>
</Pressable>
</Modal>
);
}
const styles = StyleSheet.create({
background: {
backgroundColor: "rgba(0,0,0,0,6)",
flex: 1,
justifyContent: "center",
alignItems: "center",
},
whiteBox: {
width: 300,
backgroundColor: "white",
borderRadius: 4,
elevation: 2,
},
actionButton: {
padding: 16,
flexDirection: "row",
alignItems: "center",
},
icon: {
marginRight: 8,
},
text: {
fontSize: 26,
},
});
export default UploadModeModal;
Modal 컴포넌트 Props는 다음과 같다.
- visible : 컴포넌트 노출 여부
- transparent : true로 설정 시 투명 배경(default 흰색 배경)
- animationType : 트랜지션 효과 유형(slide - 위로 슬라이드, fade - 서서히 나타남, none - 없음)
- onRequestClose : 안드로이드에서 뒤로가기 버튼을 눌렀을 때 호출되는 함수
UI는 Pressable로 두개의 공간을 만들어
위 공간을 클릭하면 카메라 촬영이 실행되고, 아래 공간에는 갤러리에서 선택하기가 실행된 후 모달이 닫히도록 하였고,
해당 두 공간을 다시 Pressable로 감싸 두 공간 외에 공간을 클릭했을때 모달이 닫히도록 설정해주었다.
2. 안드로이드에서 모달 사용
안드로이드에서 모달을 띄울때는 useState를 이용해 상태값을 만들고 상태값을visible의 값으로 사용하면 된다.
import React, { useState } from "react";
import { View, Pressable, Platform } from "react-native";
import Icon from "react-native-vector-icons/MaterialIcons";
import UploadModeModal from "./UploadModeModal";
import { launchImageLibrary, launchCamera } from "react-native-image-picker";
...
const imagePickerOption = {
mediaType: "photo",
maxWidth: 768,
maxHeight: 768,
includeBase64: Platform.OS === "android",
};
function CameraButton() {
// 선택 사진 또는 촬영된 사진 정보
const onPickImage = (res) => {
if (res.didCancel || !res) {
return;
}
console.log("PickImage", res);
}
// 카메라 촬영
const onLaunchCamera = () => {
launchCamera(imagePickerOption, onPickImage);
};
// 갤러리에서 사진 선택
const onLaunchImageLibrary = () => {
launchImageLibrary(imagePickerOption, onPickImage);
};
// 안드로이드를 위한 모달 visible 상태값
const [modalVisible, setModalVisible] = useState(false);
// 선택 모달 오픈
const modalOpen = () => {
if (Platform.OS === "android") { // 안드로이드
setModalVisible(true); // visible = true
} else { // iOS
}
}
return (
<>
<View>
<Pressable ... onPress={modalOpen}>
<Icon name="camera-alt" color="white" size={24} />
</Pressable>
</View>
<UploadModeModal
visible={modalVisible}
onClose={() => setModalVisible(false)}
onLaunchCamera={onLaunchCamera}
onLaunchImageLibrary={onLaunchImageLibrary} />
</>
);
}
...
export default CameraButton;
카메라 촬영와 갤러리에서 선택하는 기능은 react-native-image-picker를 사용하였다.
모달 오픈 함수(modalOpen)에는 Plaform을 사용해 안드로이드 일때 modalVisible의 값을 true로 변경해 주었고, UploadModeModal 컴포넌트에서 사용하는 인수들을 알맞게 넣어준다.
이제 한번 안드로이드에서 버튼을 눌러 정상적으로 작동하는지 확인해보자.
뒤로가기를 클릭해보면 모달이 잘 닫히는걸 확인할 수 있다.
3. iOS에서 ActionSheetIOS 사용하기
참고로 위에서 만든 모달을 iOS에서 사용해도 전혀 문제가 되지 않지만, iOS에서는 ActionSheetIOS를 사용하는 것이 더욱 자연스럽다. 먼저 ActionSheetIOS의 사용법을 알아보자. 설명은 주석으로 작성하겠다.
ActionSheetIOS.showActionSheetWithOptions(
{
options: ["작업1", "작업2", "작업3", "취소"], // 설정 버튼
title: "제목", // 모달 제목
message: "설명", // 모달 설명
destructiveButtonIndex: 3, // 빨간색 버튼 index
cancelButtonIndex: 3, // 취소 버튼의 index
},
(buttonIndex) => { // 클릭한 버튼의 index를 인수로 받아 작업 처리
if (buttonIndex === 0) {
작업1();
} else if (buttonIndex === 1) {
작업2();
} else if (buttonIndex === 2) {
작업3();
} else if (buttonIndex === 3) {
취소();
}
},
)
그럼 위 코드 modalOpen 함수의 iOS 부분을 작성해보자.
...
// 선택 모달 오픈
const modalOpen = () => {
if (Platform.OS === "android") { // 안드로이드
setModalVisible(true); // visible = true
} else { // iOS
ActionSheetIOS.showActionSheetWithOptions(
{
options: ["카메라로 촬영하기", "사진 선택하기", "취소"],
cancelButtonIndex: 2,
},
(buttonIndex) => {
if (buttonIndex === 0) {
onLaunchCamera();
} else if (buttonIndex === 1) {
onLaunchImageLibrary();
}
},
)
}
}
...
현재 iOS 시뮬레이터에 카메라가 연결이 안되어서 카메라로 촬영하기는 클릭해도 반응이 없다..
'React Native' 카테고리의 다른 글
React Native 카카오 로그인 설정 및 구현 (9) | 2023.01.10 |
---|---|
React Native 이미지 Firebase Storage에 업로드하기 (0) | 2022.03.13 |
React Native Firebase에 데이터 저장하기 (0) | 2022.03.10 |
React Native Firebase로 회원 인증하기 (0) | 2022.03.10 |
React Native 프로젝트에 Firebase 연동하기 (4) | 2022.03.07 |