Search code examples
react-nativeanimation

How to add a function call to Animated.sequence in react native


I have a button at the middle of my screen. onScroll I want the button to scale down to 0 to disappear and then scale back up to 1 to reappear in a new position at the bottom of the screen. I want to be able call setState (which controls the position of the button) in between the scale down and scale up animations. Something like the code below. Any idea of the best way to add a function call in between these two animations? Or an even better way of doing this?

animateScale = () => {
 return (
   Animated.sequence([
     Animated.timing(
       this.state.scale,
       {
         toValue: 0,
         duration: 300
       }
     ),
     this.setState({ positionBottom: true }),
     Animated.timing(
       this.state.scale,
       {
         toValue: 1,
         duration: 300
       }
     )
   ]).start()
 )

}


Solution

  • After more research I found the answer.start() takes a callback function as shown here:

    Calling function after Animate.spring has finished

    Here was my final solution:

    export default class MyAnimatedScreen extends PureComponent {
      state = {
        scale: new Animated.Value(1),
        positionUp: true,
        animating: false,
      };
    
      animationStep = (toValue, callback) => () =>
        Animated.timing(this.state.scale, {
          toValue,
          duration: 200,
        }).start(callback);
    
      beginAnimation = (value) => {
        if (this.state.animating) return;
    
        this.setState(
          { animating: true },
          this.animationStep(0, () => {
            this.setState(
              { positionUp: value, animating: false },
              this.animationStep(1)
            );
          })
        );
      };
    
      handleScrollAnim = ({ nativeEvent }) => {
        const { y } = nativeEvent.contentOffset;
    
        if (y < 10) {
          if (!this.state.positionUp) {
            this.beginAnimation(true);
          }
        } else if (this.state.positionUp) {
          this.beginAnimation(false);
        }
      };
    
      render() {
        return (
          <View>
            <Animated.View
              style={[
                styles.buttonWrapper,
                { transform: [{ scale: this.state.scale }] },
                this.state.positionUp
                  ? styles.buttonAlignTop
                  : styles.buttonAlignBottom,
              ]}
            >
              <ButtonCircle />
            </Animated.View>
            <ScrollView onScroll={this.handleScrollAnim}>
              // scroll stuff here
            </ScrollView>
          </View>
        );
      }
    }