手勢回應器系統
手勢回應器系統管理應用程式中手勢的生命週期。當應用程式判斷使用者的意圖時,觸碰可能會經歷幾個階段。例如,應用程式需要判斷觸碰是滾動、在小工具上滑動還是點擊。這甚至可能在觸碰期間發生變化。也可能有多個同時發生的觸碰。
需要觸碰回應器系統,以允許組件協商這些觸碰互動,而無需了解其父組件或子組件的任何額外資訊。
最佳實務
為了讓您的應用程式感覺良好,每個動作都應具有以下屬性
- 回饋/高亮顯示 - 向使用者顯示什麼正在處理他們的觸碰,以及當他們釋放手勢時會發生什麼
- 可取消性 - 當執行動作時,使用者應該能夠透過將手指拖離來中止觸碰中的動作
這些功能讓使用者在使用應用程式時更加舒適,因為它允許人們在不害怕犯錯的情況下進行實驗和互動。
TouchableHighlight 和 Touchable*
回應器系統可能很複雜而難以使用。因此,我們為應該是「可點擊」的事物提供了抽象的 Touchable
實作。這使用了回應器系統,並允許您宣告式地配置點擊互動。在任何您會在網頁上使用按鈕或連結的地方,都請使用 TouchableHighlight
。
回應器生命週期
視圖可以透過實作正確的協商方法來成為觸碰回應器。有兩種方法可以詢問視圖是否想要成為回應器
View.props.onStartShouldSetResponder: evt => true,
- 此視圖是否想要在觸碰開始時成為回應器?View.props.onMoveShouldSetResponder: evt => true,
- 當視圖不是回應器時,針對視圖上的每次觸碰移動呼叫:此視圖是否想要「聲明」觸碰回應能力?
如果視圖傳回 true 並嘗試成為回應器,則會發生以下其中一種情況
View.props.onResponderGrant: evt => {}
- 視圖現在正在回應觸碰事件。現在是高亮顯示並向使用者顯示正在發生的事情的時候了View.props.onResponderReject: evt => {}
- 其他東西現在是回應器,並且不會釋放它
如果視圖正在回應,則可以呼叫以下處理常式
View.props.onResponderMove: evt => {}
- 使用者正在移動手指View.props.onResponderRelease: evt => {}
- 在觸碰結束時觸發,即「touchUp」View.props.onResponderTerminationRequest: evt => true
- 其他東西想要成為回應器。此視圖是否應該釋放回應器?傳回 true 允許釋放View.props.onResponderTerminate: evt => {}
- 回應器已從視圖中移除。可能是被其他視圖在呼叫onResponderTerminationRequest
後取得,或者可能是被作業系統在未經詢問的情況下取得(在 iOS 上使用控制中心/通知中心時會發生)
evt
是一個具有以下形式的合成觸碰事件
nativeEvent
changedTouches
- 自上次事件以來已變更的所有觸碰事件的陣列identifier
- 觸碰的 IDlocationX
- 觸碰的 X 位置,相對於元素locationY
- 觸碰的 Y 位置,相對於元素pageX
- 觸碰的 X 位置,相對於根元素pageY
- 觸碰的 Y 位置,相對於根元素target
- 接收觸碰事件的元素的節點 IDtimestamp
- 觸碰的時間識別碼,對於速度計算很有用touches
- 螢幕上所有目前觸碰的陣列
捕捉 ShouldSet 處理常式
onStartShouldSetResponder
和 onMoveShouldSetResponder
以冒泡模式呼叫,其中最深層的節點首先被呼叫。這表示當多個視圖為 *ShouldSetResponder
處理常式傳回 true 時,最深層的組件將成為回應器。這在大多數情況下是理想的,因為它可以確保所有控制項和按鈕都可用。
但是,有時父組件會希望確保它成為回應器。這可以透過使用捕捉階段來處理。在回應器系統從最深層的組件冒泡之前,它會執行捕捉階段,觸發 on*ShouldSetResponderCapture
。因此,如果父視圖想要防止子組件在觸碰開始時成為回應器,它應該有一個傳回 true 的 onStartShouldSetResponderCapture
處理常式。
View.props.onStartShouldSetResponderCapture: evt => true,
View.props.onMoveShouldSetResponderCapture: evt => true,
PanResponder
對於更進階的手勢解譯,請查看PanResponder。