Search code examples
javascriptreactjsreact-nativeandroid-animationreact-native-animatable

Smooth swipe up animation (React Native Animation)


What do I expect to do:

A modal screen that you can close by swiping up.

Inside the modal I have:

 componentWillMount() {
    this.animated = new Animated.Value(0);

    this.panResponder = PanResponder.create({
        onStartShouldSetPanResponder: (evt, gestureState) => true,

        onPanResponderMove: (e, gestureState) => {
            const { dy } = gestureState;
            if(dy < 0) {
                this.animated.setValue(dy);
            }
        },

        onPanResponderRelease: (e, gestureState) => {
            const { dy } = gestureState;

            if(dy < -100) { // Swipe up away
                Animated.timing(this.animated, {
                    toValue: -400,
                    duration: 150
                }).start();
                this.props.hideModal();
                this.doSomething();
            } else if(dy > -100 && dy < 0) { // Swipe back to initial position
                Animated.timing(this.animated, {
                    toValue: 0,
                    duration: 150
                }).start();
            }
        }
    })
}

This Modal appears by clicking on a button in a parent component. By default in that parent there is a state value showModal : false. Opening the Modal this state is changed to true and when closing to false.

The main problem for now is that when you swipe for closing this Modal doesn't go up smoothly and disappear. It goes up to 100px, stops on a place and starts disappearing.

If remove this.props.hideModal() this Modal goes up to the top of a screen smoothly and disappears as I want, but it is not closed completely and you can not click on any other buttons after that.

Basically, I need to run this.props.hidModal() AFTER the animation has been finished.

How can I implement smooth closing of the Modal? I hope I described my problem understandably.


Solution

  • If calling this.props.hideModal() after the animatiom is finished is the fix (which I believe it is) you could pass this as a callback to .start().

    Animated.timing({..}).start(this.props.hideModal)