PanResponder reconciles several touches into a single gesture. It makes
single-touch gestures resilient to extra touches, and can be used to
recognize simple multi-touch gestures.
It provides a predictable wrapper of the responder handlers provided by the
gesture responder system.
For each handler, it provides a new gestureState object alongside the
normal event.
A gestureState object has the following:
- stateID- ID of the gestureState- persisted as long as there at least
 one touch on screen
- moveX- the latest screen coordinates of the recently-moved touch
- moveY- the latest screen coordinates of the recently-moved touch
- x0- the screen coordinates of the responder grant
- y0- the screen coordinates of the responder grant
- dx- accumulated distance of the gesture since the touch started
- dy- accumulated distance of the gesture since the touch started
- vx- current velocity of the gesture
- vy- current velocity of the gesture
- numberActiveTouches- Number of touches currently on screeen
Basic Usage #
  componentWillMount: function() {
    this._panResponder = PanResponder.create({
           onStartShouldSetPanResponder: (evt, gestureState) => true,
      onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
      onMoveShouldSetPanResponder: (evt, gestureState) => true,
      onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,
      onPanResponderGrant: (evt, gestureState) => {
              
             },
      onPanResponderMove: (evt, gestureState) => {
       
                    },
      onPanResponderTerminationRequest: (evt, gestureState) => true,
      onPanResponderRelease: (evt, gestureState) => {
                    },
      onPanResponderTerminate: (evt, gestureState) => {
                    },
      onShouldBlockNativeResponder: (evt, gestureState) => {
                      return true;
      },
    });
  },
  render: function() {
    return (
      <View {...this._panResponder.panHandlers} />
    );
  },
Working Example #
To see it in action, try the
PanResponder example in UIExplorer
Methods #
static create(config: object) #
@param {object} config Enhanced versions of all of the responder callbacks
that provide not only the typical ResponderSyntheticEvent, but also the
PanResponder gesture state.  Simply replace the word Responder with
PanResponder in each of the typical onResponder* callbacks. For
example, the config object would look like:
- onMoveShouldSetPanResponder: (e, gestureState) => {...}
- onMoveShouldSetPanResponderCapture: (e, gestureState) => {...}
- onStartShouldSetPanResponder: (e, gestureState) => {...}
- onStartShouldSetPanResponderCapture: (e, gestureState) => {...}
- onPanResponderReject: (e, gestureState) => {...}
- onPanResponderGrant: (e, gestureState) => {...}
- onPanResponderStart: (e, gestureState) => {...}
- onPanResponderEnd: (e, gestureState) => {...}
- onPanResponderRelease: (e, gestureState) => {...}
- onPanResponderMove: (e, gestureState) => {...}
- onPanResponderTerminate: (e, gestureState) => {...}
- onPanResponderTerminationRequest: (e, gestureState) => {...}
- 'onShouldBlockNativeResponder: (e, gestureState) => {...}' - In general, for events that have capture equivalents, we update the
gestureState once in the capture phase and can use it in the bubble phase
as well. - Be careful with onStartShould* callbacks. They only reflect updated
- gestureStatefor start/end events that bubble/capture to the Node.
Once the node is the responder, you can rely on every start/end event
being processed by the gesture and- gestureStatebeing updated
accordingly. (numberActiveTouches) may not be totally accurate unless you
are the responder.
 
'use strict';
var React = require('react-native');
var {
  PanResponder,
  StyleSheet,
  View,
  processColor,
} = React;
var CIRCLE_SIZE = 80;
var CIRCLE_COLOR = 'blue';
var CIRCLE_HIGHLIGHT_COLOR = 'green';
var PanResponderExample = React.createClass({
  statics: {
    title: 'PanResponder Sample',
    description: 'Shows the use of PanResponder to provide basic gesture handling.',
  },
  _panResponder: {},
  _previousLeft: 0,
  _previousTop: 0,
  _circleStyles: {},
  circle: (null : ?{ setNativeProps(props: Object): void }),
  componentWillMount: function() {
    this._panResponder = PanResponder.create({
      onStartShouldSetPanResponder: this._handleStartShouldSetPanResponder,
      onMoveShouldSetPanResponder: this._handleMoveShouldSetPanResponder,
      onPanResponderGrant: this._handlePanResponderGrant,
      onPanResponderMove: this._handlePanResponderMove,
      onPanResponderRelease: this._handlePanResponderEnd,
      onPanResponderTerminate: this._handlePanResponderEnd,
    });
    this._previousLeft = 20;
    this._previousTop = 84;
    this._circleStyles = {
      style: {
        left: this._previousLeft,
        top: this._previousTop
      }
    };
  },
  componentDidMount: function() {
    this._updatePosition();
  },
  render: function() {
    return (
      <View
        style={styles.container}>
        <View
          ref={(circle) => {
            this.circle = circle;
          }}
          style={styles.circle}
          {...this._panResponder.panHandlers}
        />
      </View>
    );
  },
  _highlight: function() {
    this.circle && this.circle.setNativeProps({
      style: {
        backgroundColor: processColor(CIRCLE_HIGHLIGHT_COLOR)
      }
    });
  },
  _unHighlight: function() {
    this.circle && this.circle.setNativeProps({
      style: {
        backgroundColor: processColor(CIRCLE_COLOR)
      }
    });
  },
  _updatePosition: function() {
    this.circle && this.circle.setNativeProps(this._circleStyles);
  },
  _handleStartShouldSetPanResponder: function(e: Object, gestureState: Object): boolean {
       return true;
  },
  _handleMoveShouldSetPanResponder: function(e: Object, gestureState: Object): boolean {
       return true;
  },
  _handlePanResponderGrant: function(e: Object, gestureState: Object) {
    this._highlight();
  },
  _handlePanResponderMove: function(e: Object, gestureState: Object) {
    this._circleStyles.style.left = this._previousLeft + gestureState.dx;
    this._circleStyles.style.top = this._previousTop + gestureState.dy;
    this._updatePosition();
  },
  _handlePanResponderEnd: function(e: Object, gestureState: Object) {
    this._unHighlight();
    this._previousLeft += gestureState.dx;
    this._previousTop += gestureState.dy;
  },
});
var styles = StyleSheet.create({
  circle: {
    width: CIRCLE_SIZE,
    height: CIRCLE_SIZE,
    borderRadius: CIRCLE_SIZE / 2,
    backgroundColor: CIRCLE_COLOR,
    position: 'absolute',
    left: 0,
    top: 0,
  },
  container: {
    flex: 1,
    paddingTop: 64,
  },
});
module.exports = PanResponderExample;