.

[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에서의 이름은 낙타방식이다.

반응형

블로그의 정보

정윤상이다.

담배맛구마

활동하기