SelectPhoto.js

김종민·2022년 6월 9일
0

insta-native

목록 보기
25/36

**들어가기
이번 POST에서는 reactNative에서 media(photo, viedo etc..)를 다루는
방법을 알아보는데 ,이번 page에서는 폰에 있는 사진을 불러들이고,
선택하는 방법을 알아본다.
1. 폰의 사진을 불러들인다(내가 만들고 있는 어플에)
2. 사진을 선택해서 upload 페이지로 이동시킨다.
3. media관련 부분은 어렵기 떄문에 최대한 집중하고, 공식문서를 항상 참조할것!

**

https://docs.expo.dev/versions/latest/sdk/media-library/

expo install expo-media-library

1. screens/Select.js

이 screen은 UploadNav의 materialTopNavigator의 page임.

import React, { useEffect, useState } from 'react'
import { Ionicons } from '@expo/vector-icons'
import styled from 'styled-components/native'
import * as MediaLibrary from 'expo-media-library'  ///1)MediaLibrary를 import
import {
  Image,
  StatusBar,
  TouchableOpacity,
  useWindowDimensions,
  FlatList,                        ///2) FlatList는 react-native에서 import됨을 확인
} from 'react-native'

const Container = styled.View`
  flex: 1;
  background-color: black;
`
const Top = styled.View`
  flex: 1;
  background-color: blue;
`
const Bottom = styled.View`
  flex: 1;
`

const ImageContainer = styled.TouchableOpacity``
const IconContainer = styled.View`
  position: absolute;
  bottom: 5px;
  right: 7px;
`
const HeaderRightText = styled.Text`
  color: skyblue;
  font-size: 18px;
  margin-right: 8px;
`

export default function SelectPhoto({ navigation }) {
  const { width } = useWindowDimensions()  ///폰의 가로 넓이를 확인!
  const [ok, setOk] = useState(false)   ///3)ok,setOk를 useState로 설정.
  const [photos, setPhotos] = useState([])
  const [chosenPhoto, setChosenPhoto] = useState('')
  
  const getPhotos = async () => {
  ///6) getPermissions에서 granted가 true가 됬다면, getPhotos()를 실행시킨다.
  
    if (ok) {
      const { assets: photos } = await MediaLibrary.getAssetsAsync({
        first:100,                      -->사진로딩시 100장 로딩(default는 20장)
        sortBy:['creationTime'],        -->사진 정렬, creationTime은 최신사진부터!
        mediaType:['photo'],            -->볼러들일게, 사진인지, 비디오인지 select
        // mediaType:['video','photo']
      })
      ///7)setOk가 true로 바뀌었다면, getAssetsAsync()를 통해 폰의 사진을 불러온다.
      ///assets로 받아오기 때문에 코딩을 하기 편하게 photos로 rename해 준다.
      ///사진을 loading할때의 options을 확인한다. 매우중요!!
      ///getAssetsAsync는 폰의 사진을 loading, getAlbumsAsync는 폰의 앨범을 불러옴.
      
      setPhotos(photos)
      setChosenPhoto(photos[0].uri)
      console.log(photos)
      ///8)사진을 불러왔으면, setPhotos에 photos를 담아둔다, 그전에  setPhotos useState만들것.
      ///setChosenPhoto에 첫번째 사진의 uri를 default값으로 넣어줌.
      ///역시, 그전에 setChosenPhoto useState 만들어 놓을것
      
    }
  }
  
  const getPermissions = async () => {
    const { canAskAgain } = await MediaLibrary.getPermissionsAsync()
    ///4)getPermissionsAsync()를 사용해서 권한을 확인한다. 
    ///그 권한중 canAskAgin을 뽑아준다.
    /// const permission = await MediaLibrary.getPermissionAsync()
    /// console.log(permission)을 해 보면.
    /// canAskAgain: true, expires:'never', granted:'false', status:'un~'
    /// 이라고 찍힘, IOS는 약간 다름.
    

    if (canAskAgain) {
      const { granted } = await MediaLibrary.requestPermissionsAsync()
      if (granted) {
        setOk(true)
        getPhotos()
        
    ///5)권한을 확인했으면, canAskAgain이 true이면, 권한허용을 위한 요청
    ///requestPermissionsAsync()를 보낸다.
    ///어플에서 권한 허용을 하면, granted가 true로 변한다.
    /// granted가 true로 바뀌었다면, setOk를 true로 바꾸고, getPhotos()함수를 실행한다.
      }
    }
  }
  const HeaderRight = () => (
    <TouchableOpacity
      onPress={() =>
        navigation.navigate('UploadForm', {
          file: chosenPhoto,
        })
      }
    >
      <HeaderRightText>Next</HeaderRightText>
    </TouchableOpacity>
  )
  ///9)header의 오른쪽에 Next라는 버튼을 만들어, 그 버튼을 누를 시,
  ///UploadForm page로 이동하게 하고, 이동 시, chosenPhoto를 같이 보내준다.\
  /// photo를 select하는 함수는 밑에서 작성예정.
  
  useEffect(() => {
    getPermissions()
  }, [ok])
///10)ok의 state에 따라 getPermissions 함수가 실행되게 useEffect로 설정함.

  useEffect(() => {
    navigation.setOptions({
      headerRight: HeaderRight,
    })
  }, [chosenPhoto])
  ///11)chosenPhoto의 state에 따라 headerRight에 위에서 만든 HeaderRight
  ///함수를 넣어준다.

  const choosePhoto = (uri) => {
    setChosenPhoto(uri)
  }
  ///12)폰에 loading된 사진중 클릭 시, 사진의 uri를 setChosenPhoto에 담아주는
  ///함수를 만든다.
  
  const renderPhoto = ({ item: photo }) => (
    <ImageContainer onPress={() => choosePhoto(photo.uri)}>
    	///14)사진을 클릭하면, chosenPhoto에 uri가 담기게 onPress함수를 만듬.
    
      <Image
        source={{ uri: photo.uri }}  ///15)source의 uri는 photo.uri임.
        style={{ width: width / 4, height: 100, margin: 1 }}
      />
      <IconContainer>
        <Ionicons
          name="checkbox"
          size={22}
          color={photo.uri === chosenPhoto ? 'skyblue' : 'white'}
        />
        ///16)사진의 uri가 chosenPhoto 여부에 따라 skyblue와 white로
        ///나뉘지게 코딩. IconContainer의 posiotion이 absolute임을 확인.
        
      </IconContainer>
    </ImageContainer>
  )
  ///13)FlatList에 사용 될 renderPhoto 함수 작성.

  return (
    <Container>
      <StatusBar hidden={false} />
      ///17)StatusBar는 숨기지 않음.
      
      <Top>
        {chosenPhoto !== '' ? (
          <Image
            source={{ uri: chosenPhoto }}
            style={{ width, height: '99%' }}
          />
        ) : null}
      </Top>
      ///18)screen의 윗화면은 chosenPhoto가 없으면 null로, 아니면, chosenPhoto
      ///를 윗 화면에 띄워준다.
      
      <Bottom>
        <FlatList
          data={photos}
          numColumns={4}
          keyExtractor={(photo) => photo.id}
          renderItem={renderPhoto}
        />
      </Bottom>
      ///19)아랫부분(폰에서 불러온 사진 100장)은 불러온 사진을 FlatList로
      ///100장을 뿌려준다. numColumns는 grid와 비슷, 한줄에 4장 배치
      
    </Container>
  )
}

reactNative부부의 Media부분은 매우 어려우니, 집중해서 볼것!.
그리고, 항상 공식문서를 보면서 따라갈것!!

profile
코딩하는초딩쌤

0개의 댓글