安装
yarn add react-native-gesture-handler
link到原生项目中
react-native link react-native-gesture-handler
为什么写这个文档
官方文档看的难受。React Native Gesture Handler 官网文档
为什么要使用这个库
更加的流畅、可靠。
react-native自带的PanResponder手势监视器由JS响应器系统控制而react-native-gesture-handler是在UI线程中识别和跟踪手势。
若使用RN官方提供的手势管理在与发生在主线程上的触摸交互(如iOS滑块或任何滚动视图)时,经常会遇到问题。==由于主线程必须同步决定JS或滚动视图是否应该成为响应器,而JS只能异步响应并不能立即拒绝Native事件的响应,导致手势操作被这些Native组件劫持。==
ps: 上面提到的JS不能立即拒绝Native事件的响应对应PanResponder中的onPanResponderTerminationRequest方法,当该方法返回false时表示拒绝其他组件响应当前的手势。
问题场景示例:
- 使用react-native-scroll-tab-view组件作为导航,左右切换视图。
- 在react-native-scroll-tab-view内嵌套了Slider组件或者其他使用PanResponder手势监视器实现了某些手势操作。
- 使用时常常会出现在这些子组件做滑动操作时,触发了react-native-scroll-tab-view组件的滑动的问题。
详情react-native项目中的这个issue:How to stopPropagation touch event
我解决这个问题过程: 如何在RN的可滚动组件内设置一个禁止滚动的区域
组件与方法说明
组件通用属性、方法 Common handler properties
enabled:是否响应手势操作。
shouldCancelWhenOutside:当前手势离开当前组件区域时是否进入CANCELLED或FAILD状态。
simultaneousHandlers
waitFor:等待其他事件结束时才响应手势操作
hitSlop:可以控制视图区域的哪个部分来开始识别手势。与View组件的hitSlop类似
onGestureEvent:手势ACTIVE状态时执行的回调
onHandlerStateChange:手势状态改变时的回调
事件参数
onHadlerStateChange与onGestureEvent回调的参数event(主要用到的就是nativeEvent属性)
//event的属性声明
interface event {
nativeEvent: nativeEvent
//...
}
//nativeEvent的属性声明
interface nativeEvent {
absoluteX: number //相对于根视图,指针的当前位置的X坐标(当放置多个手指时的手指或前导指针)。
absoluteY: number //相对于根视图,指针的当前位置的Y坐标(当放置多个手指时的手指或前导指针)。
handlerTag: number
numberOfPointers: number //表示当前放置在屏幕上的指针(手指)的数量。
state: number //手势处理程序的当前状态
translationX: number //手势开始到目前为止在水平方向上的移动距离。它与PanResponder中的dx类似
translationY: number //手势开始到目前为止在垂直方向上的移动距离。
velocityX: number //水平移速
velocityY: number //垂直移速
x: number //当前手势位置相对于附加PanGestureHandler的视图的X
y: number //当前手势位置相对于附加PanGestureHandler的视图的Y
}
手势操作过程中,react-native-gesture-handler提供Handlers组件的State会不断变化,开发者根据State来响应不同状态下的操作。详情查看Handler State
与PanResponder对照
说明 | PanGestureHandler | PanResponder |
---|---|---|
是否声明成为触摸手势响应者或是否声明成为移动手势的响应者 | - | onStartShouldSetPanResponder ,onMoveShouldSetPanResponder |
触摸手势开始 | onHadlerStateChange, State.BEGAN | onPanResponderGrant |
手势移动过程中执行的回调 | onHadlerStateChange, onGestureEvent, State.ACTIVE | onPanResponderMove |
手势释放 | onHadlerStateChange, State.END或State.FAILED | onPanResponderRelease |
是否将响应手势的操作交给其他组件 | - | onPanResponderTerminationRequest |
手势操作被其他组件或事件打断后的回调 | - | onPanResponderTerminate |
使用对比:
PanGestureHandler
import {PanGestureHandler, State} from 'react-native-gesture-handler'
//...
<PanGestureHandler
onHadlerStateChange = ({nativeEvent}) => {
switch (nativeEvent.state) {
case State.UNDETERMINED:
console.log('等待手势')
break;
case State.BEGAN:
console.log('手势开始')
break;
case State.CANCELLED:
console.log('手势取消')
break;
case State.ACTIVE:
console.log('手势活跃')
break;
case State.END:
console.log('手势结束')
break;
case State.FAILED:
console.log('失败')
break;
default:
console.log('其他')
break;
}
}
onGestureEvent = ({ nativeEvent }) => {
}
>
<Animated.View
//...
>
</Animated.View>
</PanGestureHandler>
PanResponder
import {PanResponder} from 'react-native'
<Animated.View
{
...PanResponder.create({
onStartShouldSetPanResponder: this._handleStartShouldSetPanResponder,
onMoveShouldSetPanResponder: this._handleMoveShouldSetPanResponder,
onPanResponderGrant: this._handlePanResponderGrant,
onPanResponderMove: this._handlePanResponderMove,
onPanResponderRelease: this._handlePanResponderEnd,
onPanResponderTerminationRequest: this._handlePanResponderRequestEnd,
onPanResponderTerminate: this._handlePanResponderEnd,
}).panHandlers
}
>
</Animated.View>