shunshunoki
shunshunoki

Reputation: 27

I want to close ReactNative's Modal by swiping down

I want to be able to swipe down and close the full screen modal.

I tried React-native-modal, but it was not suitable for my app.

I tried the method using GestureRecognizer on this page and was able to close the modal, but the modal did not go up and down according to the swipe, which is not ideal for me. I want to close the full screen modal with an animation like when I specify pageSheet in presentationStyle.

If you know more about it, please let me know how to do it.

const RecordingModal = ({ open, close }) => {
  return (
    <Modal
      animationType="slide"
      onSwipeComplete={close}
      presentationStyle="fullscreen"
      visible={open}
    >
      <SafeAreaView style={styles.modal}>
        <Text>aaaa</Text>
        <Text>aaaa</Text>
      </SafeAreaView>
    </Modal>
  );
};

Upvotes: 1

Views: 5015

Answers (2)

Mahdieh Shavandi
Mahdieh Shavandi

Reputation: 8645

You can implement this behavior by using react-native-modal, react-native-reanimated plus react-native-gesture-handler.

Here is an example:

import Animated, {
  runOnJS,
  useAnimatedGestureHandler,
  useAnimatedStyle,
  useSharedValue,
} from 'react-native-reanimated';

import { GestureHandlerRootView, PanGestureHandler } from 'react-native-gesture-handler';

import Modal from 'react-native-modal'


const SwipeableModal = () => {

   const translateY = useSharedValue(0);

   const gestureHandler = useAnimatedGestureHandler({
    onStart: (_, ctx) => {
      ctx.startY = translateY.value;
    },
    onActive: (event, ctx) => {
      translateY.value = ctx.startY + event.translationY;
    },
    onEnd: _ => {
      if (onClose) {
        // replace `onClose` with your close function
        runOnJS(onClose)();
      }
    },
  });

  const animatedStyle = useAnimatedStyle(() => {
    return {
      transform: [
        {
          translateY: translateY.value,
        },
      ],
    };
  });
   

  return (

    <Modal isVisible={isVisible}>
    <GestureHandlerRootView style={{flex:1}}>
       <PanGestureHandler onGestureEvent={gestureHandler}>
         <Animated.View style={[styles.myStyle, animatedStyle]}
           {.... your modal UI here}
         </Animated.View>
       </PanGestureHnadler>
    </GestureHandlerRootView>
  </Modal>

  )

}

export default SwipeableModal;

Upvotes: 0

Nooruddin Lakhani
Nooruddin Lakhani

Reputation: 6967

Try this way

<GestureRecognizer
  style={{flex: 1}}
  onSwipeUp={ () => this.setModalVisible(true) }
  onSwipeDown={ () => this.setModalVisible(false) }
>
  <Modal 
    animationType="slide"
    presentationStyle="formSheet"
    visible={ modalVisible }
  >
    <Text>Swipe Down Please</Text>
  </Modal>
  <Text>Swipe Up Please</Text>
</GestureRecognizer>

You can also use react-native-swipe-modal-up-down Following the usage

import SwipeUpDownModal from 'react-native-swipe-modal-up-down';

  let [ShowComment, setShowModelComment] = useState(false);
  let [animateModal, setanimateModal] = useState(false);

<SwipeUpDownModal
  modalVisible={ShowComment}
  PressToanimate={animateModal}
  //if you don't pass HeaderContent you should pass marginTop in view of ContentModel to Make modal swipeable
  ContentModal={
    <View style={styles.containerContent}>
      <FlatList
        data={data}
        renderItem={({item, index}) => (
          <item key={index} Data={item} />
        )}
        keyExtractor={item => item.id}
      />
    </View>
  }
  HeaderStyle={styles.headerContent}
  ContentModalStyle={styles.Modal}
  HeaderContent={
    <View style={styles.containerHeader}>
          <Button 
              Title={"Press Me"}
              onPress={() => {
                setanimateModal(true);
              }}
           />
    </View>
  }
  onClose={() => {
      setModelComment(false);
      setanimateModal(false);
  }}
/>

const styles = StyleSheet.create({
  containerContent: {flex: 1, marginTop: 40},
  containerHeader: {
    flex: 1,
    alignContent: 'center',
    alignItems: 'center',
    justifyContent: 'center',
    height: 40,
    backgroundColor: '#F1F1F1',
  },
  headerContent:{
    marginTop: 0,
  },
  Modal: {
    backgroundColor: '#005252',
    marginTop: 0,
  }
});

Upvotes: 2

Related Questions