callstack / react-native-paper

Material Design for React Native (Android & iOS)
https://reactnativepaper.com
MIT License
12.81k stars 2.08k forks source link

Modal Animation #4446

Open halilibrahimcelik opened 3 months ago

halilibrahimcelik commented 3 months ago

How can we customize modal animation? I'm trying to customize animation of modal while showing up. Instead of default fadeIn fadeOut animation, I want to insert custom animation, is there any way to change defualt modal animation in react-native-paper ? I tried Animated from react native but it did not work.

import { useFocusEffect } from '@react-navigation/native';
import { Animated } from 'react-native';
import { Modal, Portal, Text, Button, PaperProvider } from 'react-native-paper';

const DefaultModal = () => {
  const [visible, setVisible] = React.useState(false);
  const fadeAnim = React.useRef(new Animated.Value(0)).current; // Initial value for opacity: 0

  const showModal = () => setVisible(true);
  const hideModal = () => setVisible(false);
  const containerStyle = { backgroundColor: 'white', padding: 3 };
  useFocusEffect(() => {
    Animated.timing(fadeAnim, {
      toValue: 1,
      duration: 1000,
      useNativeDriver: true,
    }).start();
    return () => {
      Animated.timing(fadeAnim, {
        toValue: 0,
        duration: 250,
        useNativeDriver: true,
      }).start();
    };
  });

  return (
    <>
      <Portal>
        <Modal
          visible={visible}
          onDismiss={hideModal}
          contentContainerStyle={[
            containerStyle,
            {
              transform: [
                {
                  translateY: fadeAnim.interpolate({
                    inputRange: [0, 1],
                    outputRange: [55, 0],
                  }),
                },
              ],
            },
          ]}
        >
          <Text>Example Modal. Click outside this area to dismiss.</Text>
        </Modal>
      </Portal>
      <Button style={{ marginTop: 30 }} onPress={showModal}>
        Show
      </Button>
    </>
  );
};

export default DefaultModal;
gedu commented 3 months ago

Hey, at least for now there isn't a way to override the Modal animation

halilibrahimcelik commented 3 months ago

good thing to know, as an alternative way I used react navigation stack screen modal option

BEGDAR8ZOUHAIR commented 2 months ago

Use Animated to control the visibility and animation of the modal. Wrap the Modal component from React Native Paper inside the custom component. Control the animation for showing and hiding the modal.

BEGDAR8ZOUHAIR commented 2 months ago
import React, { useState, useEffect, useRef } from 'react';
import { View, Text, StyleSheet, TouchableOpacity, Animated, Dimensions } from 'react-native';
import { Modal, Portal, Button } from 'react-native-paper';

const { height } = Dimensions.get('window');

const CustomModal = ({ visible, onDismiss, children }) => {
  const translateY = useRef(new Animated.Value(height)).current;

  useEffect(() => {
    if (visible) {
      Animated.timing(translateY, {
        toValue: 0,
        duration: 300,
        useNativeDriver: true,
      }).start();
    } else {
      Animated.timing(translateY, {
        toValue: height,
        duration: 300,
        useNativeDriver: true,
      }).start();
    }
  }, [visible]);

  return (
    <Portal>
      <Modal visible={visible} onDismiss={onDismiss} contentContainerStyle={styles.modal}>
        <Animated.View style={[styles.animatedContainer, { transform: [{ translateY }] }]}>
          {children}
        </Animated.View>
      </Modal>
    </Portal>
  );
};

const App = () => {
  const [modalVisible, setModalVisible] = useState(false);

  const showModal = () => setModalVisible(true);
  const hideModal = () => setModalVisible(false);

  return (
    <View style={styles.container}>
      <Button onPress={showModal}>Show Modal</Button>
      <CustomModal visible={modalVisible} onDismiss={hideModal}>
        <Text style={styles.modalContent}>This is a custom animated modal!</Text>
        <Button onPress={hideModal}>Hide Modal</Button>
      </CustomModal>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  modal: {
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
  },
  animatedContainer: {
    width: '100%',
    padding: 20,
    backgroundColor: 'white',
    borderRadius: 10,
  },
  modalContent: {
    marginBottom: 20,
  },
});

export default App;