Course Menu

Gestures and Animations

PanResponder

PanResponder is used to extend the touch abilities of a particular element. It provides an API that allows you to define all the specific negotiations needed to start a touch event the way you need it.

Typically adding a touch event is straight forward, however there may be times where you need to continue the touch, or respond in a specific way when the touch is stolen from you. We won't go too deep into all of PanResponder but if you want to read more about understanding it you can access my free content on it here.

Dragging/Flicking are common actions taken in mobile applications. This will typically be orchestrated with PanResponder and the series of methods it provides to help.

onPanResponderGrant

This is typically used for setting up your animation and animated values. This will only ever be called once per gesture handling. For drag animations you likely want to call extractOffset here to allow for your delta drag movements to be applied as offsets.

More on this can be covered in stagger heads tutorial.

onPanResponderMove

This is generally going to be used with Animated.ValueXY and Animated.event to achieve dragging animations. This function will be called multiple times, every time a new drag motion is made. So be sure that you are the animations you are triggering here are interruptible.

onPanResponderMove: Animated.event([
  null,
  {
    dx: this.state.animation.x,
    dy: this.state.animation.y,
  },
]),

Check out the kitten card swiper for this style of drag animation.

However there are also other times where you need to do more complex things, like tracking animations, or decisions that are made in real time.

For example dragging over an area and transitioning the the opacity of the animation to show the user some response.

For understanding other things that can be done with onPanResponderMove check the staggered heads animation tutorial.

Do not use onPanResponderMove to derive values for animations that need to be between 1 and 0 or whatever. This will cause you a headache, just use interpolate on the specific animated values. This will make your animations easier to reset, or just in general easier to deal with.

DO NOT DO THIS.

onPanResponderMove: (e, gestureState) => {
 this.state.animation.x.setValue(gestureState.dx/500);
 this.state.animation.y.setValue(gestureState.dy/500);
},

DO THIS

onPanResponderMove: Animated.event([
  null,
  {
    dx: this.state.animation.x,
    dy: this.state.animation.y,
  },
]),
this.state.animation.x.interpolate({
  inputRange: [0, 500],
  outputRange: [0, 1],
});

onPanResponderRelease

Our onPanResponderRelease is going to be used for making decisions, resetting to start state, or anything else that requires you to call setState. The other functions you generally want to avoid calling setState (especially onPanResponderMove), as you don't want to continually re-render while you are animating.

onPanResponderRelease is only called once with the final gesture, including the velocity of the last touch, the final page position, the final delta movement, etc. This is the best spot to be able to make decisions of how to transition the UI to it's next state, or reset it.

You can learn more about onPanResponderRelease and how to use it to make decisions in the kitten card tutorial.