文檔來源:
分離類型handler, 點(diǎn)擊手勢(shì)用來識(shí)別一個(gè)或多個(gè)手指觸摸屏幕。這些手勢(shì)中涉及的手指不得從初始觸摸點(diǎn)顯著的移動(dòng)??膳渲玫模?/p>
- 手指必須觸摸屏幕的次數(shù)
- 允許的距離(allowable distance)
例如,可以用來檢測(cè)是單次點(diǎn)擊,還是雙擊,還是連續(xù)3次點(diǎn)擊
如果要激活handler,指定的手指的數(shù)量必須在適當(dāng)?shù)臅r(shí)間內(nèi)以足夠短的延遲點(diǎn)擊視圖達(dá)到指定的次數(shù), 當(dāng)handler被激活了,State立馬變?yōu)?END 狀態(tài), 如果手指移動(dòng)的距離超過了可允許的距離(allowable distance),則handler會(huì)識(shí)別失敗
屬性 (Properties)
屬性除了公用屬性外,下面是 PanGestureHandler 的特定屬性:
-
minPointers: handler被激活前放置的手指的數(shù)量 -
maxDurationMs: 定義觸摸后手指釋放的時(shí)間,單位 ms -
maxDelayMs:如果是多次點(diǎn)擊,則下一次點(diǎn)擊和上一次點(diǎn)擊之間的最大時(shí)間間隔, 單位ms -
numberOfTaps:定義激活handler需要的點(diǎn)擊次數(shù) -
maxDeltaX:當(dāng)手指沿著X軸移動(dòng)給定的距離,handler如果還沒有被激活,則識(shí)別將失敗,單位 points -
maxDeltaY:同上,針對(duì)Y軸方向 -
maxDist:手指移動(dòng)給定距離,handler如果還沒有被激活,則識(shí)別將失敗,單位 points,注意這個(gè)沒有指定方向
事件數(shù)據(jù) (event data)
除了基本的event屬性,下面是 TapGestureHandler特定的event屬性:
-
x:當(dāng)前手指相對(duì)于handler給定的視圖上的x坐標(biāo)(多個(gè)手指時(shí),以第一個(gè)手指觸摸的點(diǎn)為準(zhǔn)),單位 points -
y: 同上,表示y坐標(biāo) -
absoluteX:當(dāng)前手指相對(duì)于handler 根視圖 上的x坐標(biāo)(多個(gè)手指時(shí),以第一個(gè)手指觸摸的點(diǎn)為準(zhǔn)),推薦使用這個(gè)屬性,而不是x屬性,因?yàn)檫@個(gè)屬性是相對(duì)于根視圖的坐標(biāo)位置,不會(huì)受到當(dāng)前視圖transform之后的影響, 單位 points -
absoluteY:同上,針對(duì)Y軸
示例 多次點(diǎn)擊
import React, { PureComponent } from 'react';
import { StyleSheet, View } from 'react-native';
import { LongPressGestureHandler, ScrollView, State, TapGestureHandler } from 'react-native-gesture-handler';
import LoremIpsum from '../common';
const styles = StyleSheet.create({
scrollView: {
flex: 1,
paddingHorizontal: 10,
paddingVertical: 20,
},
box: {
width: 150,
height: 150,
backgroundColor: '#211234',
}
})
class PressBox extends PureComponent {
doubleTapRef = React.createRef(); // 只能使用這種方式創(chuàng)建ref
_onHandlerStateChange = event => {
if (event.nativeEvent.state === State.ACTIVE) {
// 如果是激活狀態(tài)
alert('按了很長(zhǎng)時(shí)間了');
}
}
_onSingleTap = event => {
// event.nativeEvent 打印結(jié)果
// { x: 0,
// absoluteX: 0,
// absoluteY: 0,
// target: 89,
// handlerTag: 8,
// y: 0,
// oldState: 4,
// numberOfPointers: 0,
// state: 5 }
console.log('單次點(diǎn)擊 event.nativeEvent', event.nativeEvent);
if (event.nativeEvent.state === State.ACTIVE) {
alert('點(diǎn)擊了一次');
}
}
_onDoubleTap = event => {
console.log('雙擊 event.nativeEvent', event.nativeEvent);
if (event.nativeEvent.state === State.ACTIVE) {
alert('點(diǎn)擊了2次');
}
}
// 單擊Handler 使用 waitFor 屬性 在 雙擊Handler 在 'BEGAN' 狀態(tài)時(shí),是不會(huì)被激活的
render() {
return (
<LongPressGestureHandler
onHandlerStateChange={this._onHandlerStateChange}
minDurationMs={800}
>
<TapGestureHandler
onHandlerStateChange={this._onSingleTap}
waitFor={this.doubleTapRef}
>
<TapGestureHandler
ref={this.doubleTapRef}
onHandlerStateChange={this._onDoubleTap}
numberOfTaps={2}
>
<View style={styles.box} />
</TapGestureHandler>
</TapGestureHandler>
</LongPressGestureHandler>
)
}
}
export default class MultiTapExample extends PureComponent {
render() {
return (
<ScrollView style={styles.scrollView}>
<LoremIpsum words={40} />
<PressBox />
<LoremIpsum />
</ScrollView>
)
}
}
這個(gè)示例用到的屬性和前面的 PanGestureHandler 有點(diǎn)不一樣:
- 用到了跨handlers之間的交互,這里使用到了
LongGestrueHandler和TapGestureHandler之間的嵌套使用的情況 - 使用到了
React.createRef()創(chuàng)建ref,配合waitFor屬性一起使用的情況 -
onHanlderStateChange的回調(diào)函數(shù)中,使用event.nativeEvent.state來判斷當(dāng)前狀態(tài),而在PanGestureHandler中使用的是event.nativeEvent.oldState進(jìn)行判斷,注意2者之間的區(qū)別 -
waitFor: 接收一個(gè)React ref 或者 refs數(shù)組 (只能使用React.ref()創(chuàng)建),指向其它組件,設(shè)置了這個(gè)屬性的Handler (假設(shè)是A)將在ref指向的handler(s) (B,C...) 的state在 'BEGAN' 時(shí),A handler就不會(huì)激活