PanResponder
PanResponder
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.
By default, PanResponder
holds an InteractionManager
handle to block long-running JS events from interrupting active 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 native event object:
onPanResponderMove: (event, gestureState) => {}
A native event is a synthetic touch event with the following form:
-
nativeEvent
-
changedTouches
- Array of all touch events that have changed since the last event -
identifier
- The ID of the touch -
locationX
- The X position of the touch, relative to the element -
locationY
- The Y position of the touch, relative to the element -
pageX
- The X position of the touch, relative to the root element -
pageY
- The Y position of the touch, relative to the root element -
target
- The node id of the element receiving the touch event -
timestamp
- A time identifier for the touch, useful for velocity calculation -
touches
- Array of all current touches on the screen
-
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 screen
Basic Usage
componentWillMount: function() { this._panResponder = PanResponder.create({ // Ask to be the responder: onStartShouldSetPanResponder: (evt, gestureState) => true, onStartShouldSetPanResponderCapture: (evt, gestureState) => true, onMoveShouldSetPanResponder: (evt, gestureState) => true, onMoveShouldSetPanResponderCapture: (evt, gestureState) => true, onPanResponderGrant: (evt, gestureState) => { // The gesture has started. Show visual feedback so the user knows // what is happening! // gestureState.d{x,y} will be set to zero now }, onPanResponderMove: (evt, gestureState) => { // The most recent move distance is gestureState.move{X,Y} // The accumulated gesture distance since becoming responder is // gestureState.d{x,y} }, onPanResponderTerminationRequest: (evt, gestureState) => true, onPanResponderRelease: (evt, gestureState) => { // The user has released all touches while this view is the // responder. This typically means a gesture has succeeded }, onPanResponderTerminate: (evt, gestureState) => { // Another component has become the responder, so this gesture // should be cancelled }, onShouldBlockNativeResponder: (evt, gestureState) => { // Returns whether this component should block native components from becoming the JS // responder. Returns true by default. Is currently only supported on android. return true; }, }); }, render: function() { return ( <View {...this._panResponder.panHandlers} /> ); },
Working Example
To see it in action, try the PanResponder example in RNTester
Methods
static create(config)
@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
gestureState
for 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 andgestureState
being updated accordingly. (numberActiveTouches) may not be totally accurate unless you are the responder.
© 2015–2017 Facebook Inc.
Licensed under the Creative Commons Attribution 4.0 International Public License.
https://facebook.github.io/react-native/docs/panresponder.html