지금 FeedList에는 사용자 경험과 관련해 한 가지 문제가 있습니다.
내용이 많아지면 우측 하단의 버튼이 항목의 내용을 가리게 됩니다.
이 문제를 해결 하기 위해선 사용자가 스크롤을 최하단으로 내릴 때 해당 버튼을 숨겨야됩니다.
애니메이션 연습히기
리액트 네이티브에서 에니메이션을 구현할 때는 animated라는 객체를 사용합니다.
import React,{useRef} from 'react';
import {Animated} from 'react-native';
function Sample() {
const animation = useRef(new Animated.Value(1)).current
}
Value를 만들 때는 이렇게 useRef를 사용해야 합니다.
이전엔 컴포넌트 레퍼런스에 포커스를 줄 때 사용하였는데
래퍼런스 선택 외에 컴포넌트 생성 시에 설정하고 , 사라질 때까지 재사용 하고 싶을 때도 사용하여 구현할 수 있습니다.
<Animated.View style={{opacity: animation}}></Animated.View>
Animated. 뒤에 사용하고 ㅣㅍ은 리액트 네이티브 컴포넌트의 이름을 넣어주면 됩니다.
이 예시 코드에서는 컴포넌트의 투명도 값을 animation이 가르키고 있는 값으로 설정했습니다.
추후 이 값을 변경할 때는 Animation.timing이라는 함수를 사용해야 합니다.
Animated.timing(animation. {
toValue : 0, // 어떤 값으로 변경할지 -필수
duration : 1000, // 애니메이션에 걸리는 시간(밀리세컨드) - 기본값 : 500
delay : 0, // 딜레이 이후 에니메이션 시작 - 기본값 : 0
useNativeDriver: true , // 네이티브 드라이버 사용 여부 - 필수
isInteraction : true, // 사용자 인터렉션에 의해 시작된 애니메이션인지 지정 - 기본값 : true
// 애니메이션 속도 변경 함수 - 기본 값 : Easing.inOt(Easing.ease)
easing: Easing.inOut(Easing.ease),
}).start(() => {
// 애니메이션 처리 완료 후 실행할 작업
})
여기서 toValue, useNativeDriver값은 필수로 지정해야 합니다.
useNativeDriver는 애니메이션 처리 작업을 자바스크립트 엔진이 아닌
네이티브 레벨에서 진행하게 하는 옵션이며 tranfroms, opacity처럼
레이아웃과 관련 없는 스타일에만 적용할 수 있습니다.
애니메이션은 .start()로 시작하고
이 함수 끝에 콜백 함수를 인자로 넣어주면 에니메이션이 끝난 후 호출됩니다.
이제 CalendarScreen에 연습을 하겠습니다.
Fade In ,Fade Out 효과 입니다.
screens/CalendarScreen.js
import React, {useRef} from 'react';
import {View, StyleSheet, Text, Animated, Button} from 'react-native';
function FadeInAndOut() {
const animation = useRef(new Animated.Value(1)).current;
return (
<View>
<Animated.View
style={[
styles.rectangle,
{
opacity: animation,
},
]}
/>
<Button
title={'FadeIn'}
onPress={() => {
Animated.timing(animation, {
toValue: 0,
useNativeDriver: true,
}).start();
}}
/>
</View>
);
}
function CalendarScreen() {
return (
<View style={styles.block}>
<FadeInAndOut />
</View>
);
}
const styles = StyleSheet.create({
block: {},
rectangle: {
width: 100,
height: 100,
backgroundColor: 'black',
},
});
export default CalendarScreen;
지금은 두개의 버튼으로 하였지만
상태값에 따라 하나의 버튼으로 하고싶다면 useState와 useEffect를 사용합니다.
screens/CalendarScreen.js
import React, {useEffect, useRef, useState} from 'react';
import {View, StyleSheet, Text, Animated, Button} from 'react-native';
function FadeInAndOut() {
const animation = useRef(new Animated.Value(1)).current;
const [hidden, setHidden] = useState(false);
useEffect(() => {
Animated.timing(animation, {
toValue: hidden ? 0 : 1,
useNativeDriver: true,
}).start();
}, [hidden, animation]);
return (
<View>
<Animated.View
style={[
styles.rectangle,
{
opacity: animation,
},
]}
/>
<Button
title={'Toggle'}
onPress={() => {
setHidden(!hidden);
}}
/>
</View>
);
}
function CalendarScreen() {
return (
<View style={styles.block}>
<FadeInAndOut />
</View>
);
}
const styles = StyleSheet.create({
block: {},
rectangle: {
width: 100,
height: 100,
backgroundColor: 'black',
},
});
export default CalendarScreen;
이번엔 좌우로 움직이기를 구현해보겠습니다.
컴포넌트를 움직일 때는 꼭 필요하지 않다면 left,top 스타일 보다는 tarnsfrom 스타일을 사용하는 것이
성능면에서 더 좋습니다.
{
tarnfrom : [{translateX: 100} , {translsateY: 50}]
}
다음 코드를 기존 FadeInAndOut 컴포넌트를 지우고 만들어 봅시다.
import React, {useEffect, useRef, useState} from 'react';
import {View, StyleSheet, Text, Animated, Button} from 'react-native';
function SlideLeftAndRight() {
const animation = useRef(new Animated.Value(1)).current;
const [enable, setEnable] = useState(false);
useEffect(() => {
Animated.timing(animation, {
toValue: enable ? 150 : 0,
useNativeDriver: true,
}).start();
}, [enable, animation]);
return (
<View>
<Animated.View
style={[
styles.rectangle,
{
transform: [{translateX: animation}],
},
]}
/>
<Button
title={'Toggle'}
onPress={() => {
setEnable(!enable);
}}
/>
</View>
);
}
function CalendarScreen() {
return (
<View style={styles.block}>
<SlideLeftAndRight />
</View>
);
}
const styles = StyleSheet.create({
block: {},
rectangle: {
width: 100,
height: 100,
backgroundColor: 'black',
},
});
export default CalendarScreen;
이제 버튼을 누르면 오른쪽 왼쪽으로 움직이는 사각형을 확인할 수 있습니다.
이번엔 interpolate로 여러 스타일을 적용해보겠습니다
anination.interpolate({
inputRatne : [0,1],
outputRange: [0, 150]
})
사용법은 위와 같이 사용하면 됩니다.
screens.CalendarScreen.js
import React, {useEffect, useRef, useState} from 'react';
import {View, StyleSheet, Text, Animated, Button} from 'react-native';
function SlideLeftAndRight() {
const animation = useRef(new Animated.Value(1)).current;
const [enable, setEnable] = useState(false);
useEffect(() => {
Animated.timing(animation, {
toValue: enable ? 150 : 0,
useNativeDriver: true,
}).start();
}, [enable, animation]);
return (
<View>
<Animated.View
style={[
styles.rectangle,
{
transform: [
{
translateX: animation.interpolate({
inputRange: [0, 1],
outputRange: [0, 150],
}),
},
],
opacity: animation.interpolate({
inputRange: [0, 1],
outputRange: [1, 0],
}),
},
]}
/>
<Button
title={'Toggle'}
onPress={() => {
setEnable(!enable);
}}
/>
</View>
);
}
function CalendarScreen() {
return (
<View style={styles.block}>
<SlideLeftAndRight />
</View>
);
}
const styles = StyleSheet.create({
block: {},
rectangle: {
width: 100,
height: 100,
backgroundColor: 'black',
},
});
export default CalendarScreen;
이젠 정사각형이 오른쪽으로 가면서 사라지고 왼쪽으로 오면서 나타나는 것을 확인 할 수 있습니다.
'코딩생활 > ReactNative' 카테고리의 다른 글
[React Native] 3-9 작성한 글을 WriteScreen으로 열기 (0) | 2023.03.20 |
---|---|
[React Native] 3-8 스크롤 내렸을 때 글쓰기 버튼 숨기기 (0) | 2023.03.18 |
[React Native] 3-6 글 목록 보여주기 (0) | 2023.03.16 |
[React Native] 3-6 LogContext로 배열 상태 관리하기 (0) | 2023.03.15 |
[React Native] 3-4 WriteScreen 준비하기 (0) | 2023.03.14 |
댓글