개발자
안녕하세요 제가 만든 BottomSheet 컴포넌트가 있습니다. BottomSheet를 사용하는 곳에서 closeBottomSheet 을 부르면 애니메이션 없이 닫히는데 closeModal을 호출하고도 애니메이션을 주면서 닫을 수 있는 방법이 있을까요?
1// BottomSheet
2
3import React, { useEffect, useRef } from 'react';
4import {
5 View,
6 StyleSheet,
7 Text,
8 Modal,
9 Animated,
10 TouchableWithoutFeedback,
11 Dimensions,
12 PanResponder,
13} from 'react-native';
14import Color from '../../constants/color';
15import TYPOS from './typo';
16
17interface BottomSheetProps {
18 isOpened: boolean;
19 onClose: () => void;
20 children: React.ReactNode;
21 height: number;
22}
23
24const BottomSheet = ({
25 isOpened,
26 onClose,
27 children,
28 height,
29}: BottomSheetProps) => {
30 const screenHeight = Dimensions.get('screen').height;
31 const panY = useRef(new Animated.Value(screenHeight)).current;
32 const translateY = panY.interpolate({
33 inputRange: [-1, 0, 1],
34 outputRange: [0, 0, 1],
35 });
36
37 const resetBottomSheet = Animated.timing(panY, {
38 toValue: 0,
39 duration: 300,
40 useNativeDriver: true,
41 });
42
43 const closeBottomSheet = Animated.timing(panY, {
44 toValue: screenHeight,
45 duration: 300,
46 useNativeDriver: true,
47 });
48
49 const panResponders = useRef(
50 PanResponder.create({
51 onStartShouldSetPanResponder: () => true,
52 onMoveShouldSetPanResponder: () => false,
53 onPanResponderMove: (event, gestureState) => {
54 panY.setValue(gestureState.dy);
55 },
56 onPanResponderRelease: (event, gestureState) => {
57 if (
58 gestureState.dy > 0 &&
59 (gestureState.dy > 80 || gestureState.vy > 1.5)
60 ) {
61 closeModal();
62 } else {
63 resetBottomSheet.start();
64 }
65 },
66 })
67 ).current;
68
69 useEffect(() => {
70 if (isOpened) {
71 resetBottomSheet.start();
72 }
73 }, [isOpened]);
74
75 const closeModal = () => {
76 closeBottomSheet.start(() => {
77 onClose();
78 });
79 };
80
81 return (
82 <Modal
83 visible={isOpened}
84 animationType="fade"
85 transparent
86 statusBarTranslucent
87 >
88 <TouchableWithoutFeedback onPress={closeModal}>
89 <View style={styles.overlay}>
90 <Animated.View
91 style={[
92 styles.background,
93 {
94 opacity: panY.interpolate({
95 inputRange: [0, screenHeight],
96 outputRange: [1, 0],
97 }),
98 },
99 ]}
100 />
101 <Animated.View
102 style={[
103 styles.bottomSheetContainer,
104 {
105 height,
106 transform: [{ translateY: translateY }],
107 },
108 ]}
109 {...panResponders.panHandlers}
110 >
111 <View style={{ alignItems: 'center' }}>
112 <View
113 style={{
114 width: 44,
115 height: 4,
116 backgroundColor: '#DEDEDE',
117 marginVertical: 8,
118 }}
119 ></View>
120 </View>
121 <View>{children}</View>
122 </Animated.View>
123 </View>
124 </TouchableWithoutFeedback>
125 </Modal>
126 );
127};
128
129const styles = StyleSheet.create({
130 overlay: {
131 flex: 1,
132 justifyContent: 'flex-end',
133 backgroundColor: 'rgba(0, 0, 0, 0.4)',
134 },
135 background: {
136 ...StyleSheet.absoluteFillObject,
137 },
138 bottomSheetContainer: {
139 backgroundColor: Color.white,
140 borderTopLeftRadius: 24,
141 borderTopRightRadius: 24,
142 },
143});
144
145export default BottomSheet;
146
147// 사용하는 곳
148import React, { useState } from 'react';
149import { View, Text } from 'react-native';
150import TYPOS from '../../components/ui/typo';
151import Button from '../../components/ui/buttons/Button';
152import Color from '../../constants/color';
153import BottomSheet from '../../components/ui/BottomSheet';
154
155const Test = () => {
156 const [isVisible, setIsVisible] = useState(false);
157
158 const openBottomSheet = () => {
159 setIsVisible(true);
160 };
161
162 const closeBottomSheet = () => {
163 setIsVisible(false);
164 };
165
166 return (
167 <>
168 <View>
169 <Button label="BottomSheet" onPressHandler={openBottomSheet} />
170 </View>
171 <BottomSheet
172 isOpened={isVisible}
173 onClose={() => {
174 closeBottomSheet();
175 }}
176 height={310}
177 >
178 <View
179 style={{
180 width: '100%',
181 height: '100%',
182 }}
183 >
184 <View style={{ paddingVertical: 24, paddingHorizontal: 16 }}>
185 <Text style={[TYPOS.headline3, { color: Color.black }]}>
186 바텀 시트 내용
187 </Text>
188 </View>
189 <View style={{ marginHorizontal: 16, marginTop: 24 }}>
190 <Button label="닫기" onPressHandler={closeBottomSheet} />
191 </View>
192 </View>
193 </BottomSheet>
194 </>
195 );
196};
197export default Test;
답변 0
첫 답변을 기다리고 있어요.
지금 가입하면 모든 질문의 답변을 볼 수 있어요!
현직자들의 명쾌한 답변을 얻을 수 있어요.
이미 회원이신가요?
지금 가입하면 모든 질문의 답변을 볼 수 있어요!