手勢識別在移動設(shè)備上比在網(wǎng)絡(luò)上要復(fù)雜得多。當(dāng)應(yīng)用程序確定用戶的意圖時(shí),一個(gè)觸摸可能要經(jīng)歷幾個(gè)階段。例如,應(yīng)用程序需要確定觸摸是否是滾動,滑動部件還是輕擊。這甚至可以在觸摸期間發(fā)生改變,也可以有多個(gè)同時(shí)觸摸。
要想使組件在沒有任何額外的關(guān)于它們的父組件或子組件的知識的情況下處理這些觸摸交互,需要觸摸應(yīng)答系統(tǒng)。這個(gè)系統(tǒng)在 ResponderEventPlugin.js 中實(shí)現(xiàn)了,其中包含更多細(xì)節(jié)和文檔。
用戶在 web 應(yīng)用程序與本機(jī)的可用性上可以感覺到巨大的差異,并且這是最大的原因之一。每一個(gè)動作都應(yīng)該有以下屬性:
這些特性讓用戶使用一個(gè)應(yīng)用程序時(shí)更舒適,因?yàn)樗试S人們在實(shí)驗(yàn)和交互時(shí)不用擔(dān)心犯錯誤。
應(yīng)答系統(tǒng)在使用時(shí)可能是復(fù)雜的。所以我們?yōu)閼?yīng)該“可以輕擊的”東西提供了一個(gè)抽象的 Touchable 實(shí)現(xiàn)。這使用了應(yīng)答系統(tǒng),并且使你以聲明的方式可以輕松地識別輕擊交互。在網(wǎng)絡(luò)中任何你會用到按鈕或鏈接的地方使用 TouchableHighlight。
通過實(shí)施正確的處理方法,視圖可以成為接觸應(yīng)答器。有兩種方法來詢問視圖是否想成為應(yīng)答器:
View.props.onStartShouldSetResponder: (evt) => true,——這個(gè)視圖是否在觸摸開始時(shí)想成為應(yīng)答器?View.props.onMoveShouldSetResponder: (evt) => true,——當(dāng)視圖不是應(yīng)答器時(shí),該指令被在視圖上移動的觸摸調(diào)用:這個(gè)視圖想“聲明”觸摸響應(yīng)嗎? 如果視圖返回 true 并且想成為應(yīng)答器,那么下述的一種情況就會發(fā)生:
View.props.onResponderGrant:(evt)= > { } ——視圖現(xiàn)在正在響應(yīng)觸摸事件。這個(gè)時(shí)候要高亮標(biāo)明并顯示給用戶正在發(fā)生的事情。View.props.onResponderReject:(evt)= > { }——其他的東西時(shí)應(yīng)答器并且不會釋放它。如果視圖正在響應(yīng),那么可以調(diào)用以下處理程序:
View.props.onResponderMove:(evt)= > { }——用戶正移動他們的手指View.props.onResponderRelease:(evt)= > { }——在觸摸最后被引發(fā),即“touchUp”View.props.onResponderTerminationRequest:(evt)= >true——其他的東西想成為應(yīng)答器。這種視圖應(yīng)該釋放應(yīng)答嗎?返回 true 就是允許釋放View.props.onResponderTerminate:(evt)= > { }——應(yīng)答器已經(jīng)從視圖獲取了??赡茉谡{(diào)用 onResponderTerminationRequest 之后被其他視圖獲取,也可能是被操作系統(tǒng)在沒有請求的情況下獲取了(發(fā)生在 iOS 的 control center/notification center)evt 是一個(gè)綜合的觸摸事件,有以下形式:
nativeEvent
changedTouches——自從上個(gè)事件之后,所有發(fā)生改變的觸摸事件的數(shù)組identifier——觸摸的 IDlocationX ——觸摸相對于元素的 X 位置locationY——觸摸相對于元素的 Y 位置pageX——觸摸相對于屏幕的 X 位置pageY——觸摸相對于屏幕的 Y 位置target——接收觸摸事件的元素的節(jié)點(diǎn) idtimestamp——觸摸的時(shí)間標(biāo)識符,用于速度計(jì)算touches——所有當(dāng)前在屏幕上觸摸的數(shù)組在冒泡模式,即最深的節(jié)點(diǎn)最先被調(diào)用,的情況下,onStartShouldSetResponder 和 onMoveShouldSetResponder 被調(diào)用。這意味著,當(dāng)多個(gè)視圖為 * ShouldSetResponder 處理程序返回 true 時(shí),最深的組件會成為應(yīng)答器。在大多數(shù)情況下,這是可取的,因?yàn)樗_保了所有控件和按鈕是可用的。
然而,有時(shí)父組件會想要確保它成為應(yīng)答器。這可以通過使用捕獲階段進(jìn)行處理。在應(yīng)答系統(tǒng)從最深的組件冒泡時(shí),它將進(jìn)行一個(gè)捕獲階段,引發(fā) * ShouldSetResponderCapture。所以如果一個(gè)父視圖要防止子視圖在觸摸開始時(shí)成為應(yīng)答器,它應(yīng)該有一個(gè) onStartShouldSetResponderCapture 處理程序,返回 true。
View.props.onStartShouldSetResponderCapture: (evt) => true,View.props.onMoveShouldSetResponderCapture: (evt) => true,更高級的手勢解釋,看看 PanResponder。