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 basic multi-touch gestures.
默认情况下,PanResponder
持有 InteractionManager
句柄,以阻止长时间运行的 JS 事件中断活动手势。
¥By default, PanResponder
holds an InteractionManager
handle to block long-running JS events from interrupting active gestures.
它提供了 手势响应系统 提供的响应程序处理程序的可预测封装。对于每个处理程序,它在原生事件对象旁边提供一个新的 gestureState
对象:
¥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) => {}
原生事件是形式为 PressEvent 的合成触摸事件。
¥A native event is a synthetic touch event with form of PressEvent.
gestureState
对象具有以下内容:
¥A gestureState
object has the following:
-
stateID
- 手势状态的 ID - 只要屏幕上至少有一次触摸就会持续存在¥
stateID
- ID of the gestureState- persisted as long as there's at least one touch on screen -
moveX
- 最近移动触摸的最新屏幕坐标¥
moveX
- the latest screen coordinates of the recently-moved touch -
moveY
- 最近移动触摸的最新屏幕坐标¥
moveY
- the latest screen coordinates of the recently-moved touch -
x0
- 响应者授予的屏幕坐标¥
x0
- the screen coordinates of the responder grant -
y0
- 响应者授予的屏幕坐标¥
y0
- the screen coordinates of the responder grant -
dx
- 自触摸开始以来手势的累计距离¥
dx
- accumulated distance of the gesture since the touch started -
dy
- 自触摸开始以来手势的累计距离¥
dy
- accumulated distance of the gesture since the touch started -
vx
- 手势的当前速度¥
vx
- current velocity of the gesture -
vy
- 手势的当前速度¥
vy
- current velocity of the gesture -
numberActiveTouches
- 当前屏幕上的触摸次数¥
numberActiveTouches
- Number of touches currently on screen
使用模式
¥Usage Pattern
const ExampleComponent = () => {
const panResponder = React.useRef(
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;
},
}),
).current;
return <View {...panResponder.panHandlers} />;
};
示例
¥Example
PanResponder
与 Animated
API 配合使用,帮助在 UI 中构建复杂的手势。以下示例包含一个动画 View
组件,可以在屏幕上自由拖动
¥PanResponder
works with Animated
API to help build complex gestures in the UI. The following example contains an animated View
component which can be dragged freely across the screen
试试 RNTester 中的 PanResponder 示例。
¥Try the PanResponder example in RNTester.
参考
¥Reference
方法
¥Methods
create()
static create(config: PanResponderCallbacks): PanResponderInstance;
参数:
¥Parameters:
名称 | 类型 | 描述 |
---|---|---|
配置 必填 | object | 参考下文 |
config
对象提供了所有响应者回调的增强版本,通过在每个典型 onResponder*
回调中将单词 Responder
替换为 PanResponder
,不仅提供 PressEvent
,还提供 PanResponder
手势状态。例如,config
对象如下所示:
¥The config
object provides enhanced versions of all of the responder callbacks that provide not only the PressEvent
, but also the PanResponder
gesture state, by replacing 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) => {...}
一般来说,对于具有捕获等效项的事件,我们在捕获阶段更新一次 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.
小心 onStartShould*
回调。它们仅反映更新的 gestureState
用于冒泡/捕获到节点的开始/结束事件。一旦节点成为响应者,你就可以依赖手势处理的每个开始/结束事件以及相应更新的 gestureState
。除非你是响应者,否则 (numberActiveTouches) 可能不完全准确。
¥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 and gestureState
being updated accordingly. (numberActiveTouches) may not be totally accurate unless you are the responder.