[React-Native] 끄적이기
by 담배맛구마모듈단위로 정리해보자
Print Image on network
이미지는 출력을 Image
컴포넌트로 출력하면 되고 네트워크 상에 있는 이미지를 가져올 때에는 width와 height를 명확하게 제시를 해줘야 한다. 지정안하면 에러는 안뜨는데 그냥 안 보인다. 그래서 나는 이미지 크기와 디스플레이 크기의 비율인 ratio를 계산해서 사용했다.
let imageUri = 'http://~~/a.jpg' let imageWidth = 1080; let imageHeight = 1920; let ratio = Dimensions.get('window').height/imageHeight; return( <Image source={{uri: imageUri}} style={{width: imageWidth * ratio, height: imageHeight * ratio}} /> );
동일한 이미지를 여러번 호출 하는 경우 캐시에 담아두는 기능이 있다. 뭐.. 그렇다는데 실험은 안해봤다.
let imageUri = 'http://~~/a.jpg' Image.queryCache([imageUri]);
Device Rotate
내 폰에 테스트하다가 어쩌다가 가로모드로 바꼇는데, 렌더링이 되지는 않았다. 화면에 전환이 있을 때, 계산해서 강제로 렌더링 시켜버렸다. 강제로 렌더링하는 메소드는 this.forceUpdate();
이다.
componentDidMount(){ Dimensions.addEventListener('change', this.onChangeDimensions); } componentWillUnmount(){ Dimensions.removeEventListener('change', this.onChangeDimensions); } onChangeDimensions = () => { this.forceUpdate() }
componentDidMount()
는 초기에render()
가 실행된 이후에 실행되는 걸로 알고있는데, 이거만 하니까componentWillUnmount
정의가 안됬다고 워닝떠서 추가했다.
Touch event on Image
Image
는 기본적으로 onPress
가 없다. 터치 이벤트를 주고 싶으면 상위에 TouchableHighlight
와 같은 컴포넌트를 두고 거기에 onPress
를 줘야한다.
<TouchableHighlight onPress={this.pressImage} activeOpacity={1}> <Image source={{uri: imageUri}} style={{width: imageWidth * ratio, height: imageHeight * ratio}} /> </TouchableHighlight>
Animation on Image
클릭했을 때 서서히 어두워지는 효과를 주고 싶었다. 처음에 타이머 만들어서 직접 구현하려고 했는데 이미 Animated
라는 컴포넌트가 정의가 되어 있었다.
state = { isShowMenu : false, animateValue : new Animated.Value(1) }; pressImage = () => { this.setState({ isShowMenu: !this.state.isShowMenu }, () => { Animated.timing( this.state.animateValue, { toValue: this.state.isShowMenu? 0.5 : 1, duration: 500, useNativeDriver: true }).start(()=>{ // Console.log('Wow~') }); }); } <TouchableHighlight onPress={this.pressImage} activeOpacity={1}> <Animated.View style={{opacity: this.state.animateValue}}> <Image source={{uri: imageUri}} style={{width: imageWidth * ratio, height: imageHeight * ratio}} /> </Animated.View> </TouchableHighlight>

Filesystem
기본적으로 Filesystem에 대해서 제어하는 기능은 없고 react-antive-fs
모듈을 받아서 진행해야 한다. 이미지 데이터를 받아서 byte로 찍어되야 되나 한숨쉬다가 downloadFile
메소드 있길래 바로 써봤더니 잘 되지는 않았다. 문제는 퍼미션 문제인 것 같아서 디바이스 설정에서 수동으로 파일시스템 권한 줬더니 잘 된다. 이제 파일시스템 퍼미션 주는 방식에 대해 알아봐야겠다.
import * as RNFS from 'react-native-fs'; let imageUri = 'http://~~/a.jpg' RNFS.downloadFile({ fromUrl: imageUri, toFile: '/storage/emulated/0/Download/test.jpg' }).promise.then((r)=>{ console.log(r); });
Show menu from bottom
이걸.. Animated
로 구현해야 되나 현타왔다가 react-native-bottom-action-sheet
모듈을 쓰기로 했다. GridView
에서 visible에 state를 주면 깔끔할 것 같다. 그래서 이때까지 했던거 총합해서 메뉴가 보일 때 슈르륵 올라오게 만들었다.
import RNBottomActionSheet from 'react-native-bottom-action-sheet'; import Icon from 'react-native-vector-icons/FontAwesome5'; let saveIcon = <Icon family={'FontAwesome'} name={'save'} color={'#000000'} size={30}/> let shareIcon = <Icon family={'FontAwesome'} name={'share-alt'} color={'#000000'} size={30} /> let settingIcon = <Icon family={'FontAwesome'} name={'cog'} color={'#000000'} size={30} /> <RNBottomActionSheet.GridView visible={this.state.isShowMenu} onSelection={(index, value) => { this.pressImage(); RNFS.downloadFile({ fromUrl: imageUri, toFile: '/storage/emulated/0/Download/test.jpg' }).promise.then((r)=>{ console.log(r); }); }} onCancel={()=>{this.pressImage();}} > <RNBottomActionSheet.GridView.Item title={'저장하기'} icon={saveIcon} /> <RNBottomActionSheet.GridView.Item title={'공유하기'} icon={shareIcon} /> <RNBottomActionSheet.GridView.Item title={'설정화면'} icon={settingIcon} /> </RNBottomActionSheet.GridView>
잡다한 것들
[1] React-Native에서의 이름은 낙타방식이다.
블로그의 정보
정윤상이다.
담배맛구마