이미지 피커 만들기

React Native CameraRoll React Native ImagePicker

이 두 라이브러리를 많이 사용하는데 Expo에선 사용할 수 없음

Expo 자체 ImagePicker 가 있기에 그걸 쓰면 될 듯 MediaLibrary 도 있음.

npx expo install expo-media-library
npx expo install expo-image-picker

권한 요청의 경우

  • 맨처음 들어왔을 때
  • 권한이 필요할 때

케바케임

접근했을 때 권한 요청할 것임.

const [status, requestPermission] = MediaLibrary.usePermissions();

status 보면 granted 에서 확인할 수 있음.

그리고, 접근권한은 나중에 봐야겠지만 결국 app.json 파일 안에서 설정해주면 된다. 아래와 같이 일단은 설정함.

"ios": {
            "supportsTablet": true,
            "infoPlist": {
                "NSPhotoLibraryUsageDescription": "The app access the photo library to upload a profile photo and use it on the post"
            }
},
"android": {
    "adaptiveIcon": {
        "foregroundImage": "./assets/adaptive-icon.png",
        "backgroundColor": "#f97316"
    },
    "permission": ["READ_EXTERNAL_STORAGE"]
},

이미지 가져오기

getAssetAsync

  • after :
  • first : 한번에 몇장씩
  • sortBy : 정렬

id, filename, uri 가 필요함.

아이 몰라 코드 복사함

import {
	Alert,
	StyleSheet,
	Text,
	View,
	FlatList,
	Pressable,
	useWindowDimensions,
	Image,
} from 'react-native';
import PropTypes from 'prop-types';
import { useNavigation } from '@react-navigation/native';
import { useCallback, useEffect, useLayoutEffect, useState } from 'react';
import HeaderRight from '../components/HeaderRight';
import * as MediaLibrary from 'expo-media-library';

const ImagePickerScreen = () => {
	const navigation = useNavigation();

	const [status, requestPermission] = MediaLibrary.usePermissions();

	useEffect(() => {
		(async () => {
			const { granted } = await requestPermission();
			if (!granted) {
				Alert.alert('사진접근 권한', '접근권한이 필요합니다.', [
					{
						text: '확인',
						onPress: () =>
							navigation.canGoBack() && navigation.goBack(),
					},
				]);
			}
		})();
	}, [navigation, requestPermission]);

	const width = useWindowDimensions().width / 3;

	const [photos, setPhotos] = useState([]);
	const [listInfo, setListInfo] = useState({
		endCursor: '',
		hasNextPage: true,
	});

	const getPhotos = useCallback(async () => {
		const options = {
			first: 30,
			sortBy: [MediaLibrary.SortBy.creationTime],
		};

		if (listInfo.hasNextPage) {
			const { assets, endCursor, hasNextPage, totalCount } =
				await MediaLibrary.getAssetsAsync(options);
			setPhotos(assets);
			setListInfo({ endCursor, hasNextPage });
		}
	}, [listInfo.hasNextPage]);

	useEffect(() => {
		if (status?.granted) {
			getPhotos();
		}
	}, [status?.granted, getPhotos]);

	useLayoutEffect(() => {
		navigation.setOptions({
			headerRight: () => <HeaderRight onPress={() => {}} />,
		});
	});

	return (
		<View style={styles.container}>
			<FlatList
				key={'#'}
				style={styles.list}
				data={photos}
				renderItem={({ item }) => (
					<Pressable style={{ width, height: width }}>
						<Image
							source={{ uri: item.uri }}
							style={styles.photo}
						/>
					</Pressable>
				)}
				numColumns={3}
			/>
		</View>
	);
};

ImagePickerScreen.propTypes = {};
const styles = StyleSheet.create({
	container: {
		flex: 1,
		justifyContent: 'center',
		alignItems: 'center',
	},
	title: {
		fontSize: 30,
	},
	list: {
		width: '100%',
	},
	photo: {
		width: '100%',
		height: '100%',
	},
});
export default ImagePickerScreen;

새로고침하기

당겨서 새로고침 하는 경우 onRefresh

  • 새로고침 함수
  • 당겨서 새로고침 기능

refreshing

  • 새로고침할 때, 새 데이터를 가져오는 동안 true로 설정

사진 파일 더 가져오기

사진 선택 시 check 해주기