安裝
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>