ジェスチャーレスポンダシステム
ジェスチャーレスポンダシステムは、アプリ内のジェスチャーのライフサイクルを管理します。タッチは、アプリがユーザーの意図を判断する際にいくつかのフェーズを経ることができます。たとえば、アプリはタッチがスクロール、ウィジェット上のスライド、またはタップであるかを判断する必要があります。これは、タッチの継続時間中に変化することもあります。複数の同時タッチも発生する可能性があります。
タッチレスポンダシステムは、親または子コンポーネントに関する追加の知識なしに、コンポーネントがこれらのタッチインタラクションを調整できるようにするために必要です。
ベストプラクティス
アプリを快適に利用できるようにするには、すべての操作に次の属性が必要です。
- フィードバック/ハイライト - ユーザーに、何がタッチを処理しているのか、そしてジェスチャーを解放したときに何が起こるのかを示します。
- キャンセル可能性 - 操作を行う際、ユーザーは指を離してタッチ中に操作を中止できる必要があります。
これらの機能により、ユーザーはミスをすることを恐れることなく実験してインタラクトできるため、アプリの使用がより快適になります。
TouchableHighlightとTouchable*
レスポンダシステムは使用が複雑になる可能性があります。「タップ可能」であるべきものについては、抽象的なTouchable
実装を提供しています。これはレスポンダシステムを使用し、タップインタラクションを宣言的に構成できます。ウェブでボタンやリンクを使用する場所であればどこでも、TouchableHighlight
を使用してください。
レスポンダライフサイクル
ビューは、適切なネゴシエーションメソッドを実装することで、タッチレスポンダになることができます。ビューがレスポンダになりたいかどうかを尋ねる方法は2つあります。
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
の呼び出し後に他のビューによって奪われるか、OSによって尋ねられることなく奪われる可能性があります(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をご覧ください。