[ReactNative] subviewからタッチイベントを奪う
ネイティブアプリにおいて, ちょっと面倒だけどよく使うものの1つにsubviewのタッチイベントを無効化して, superviewがタッチイベントを処理したいケースというのがある.
iOSでいうところのUIView # hitTest:withEvent:で行う処理である.
ReactNativeの場合にどうするか, 割と分かりにくいところに書いてあったので備忘録的に書いておこうと思う.
ReactNativeでは最も深い位置のsubviewから順にresponderの判定が行われる
そもそもReactNativeでTouchableを扱おうとする場合, TouchableWithoutFeedbackを用いた派生クラスを用いる. 派生クラスと書いているが, 基本的には継承関係になく, これらを子に持つComponentである.
これらがResponderになる為のフローはGesture Responder Systemにおいて記載がある.
onStartShouldSetResponderの返り値によって, subviewから順番にresponderになるターゲットを判断するようだ.
コードでいうと, ここらへんにある.
ところで, responderの判定の仕方がiOSとは全く異なるというのが面白い. iOSはrootから順番にUIView # hitTest:withEvent:を呼び出していき, superviewからsubviewへと判断される.
一方で, ReactNativeはsubviewからsuperviewへと判定されていくのがデフォルトの挙動である.
onStartShouldSetResponder and onMoveShouldSetResponder are called with a bubbling pattern, where the deepest node is called first.
SuperviewがResponderになる方法
disabledを使う方法
先にhack的な方法を紹介する. ドキュメントに辿り着くまでにググって出てきた方法はこちらだった.
disabled
を設定することでここでonStartShouldSetResponderがfalseになることを使う方法である.
しかし, この方法だとdisabled
用のstyleが適用されてしまう. そこで, styleを自分で指定することでそれっぽい見た目にする.
onStartShouldSetResponderCaptureを使う方法
Gesture Responder Systemに記載されている, Superviewがresponderになる方法を使う.
これで設定したComponentの子要素がresponderにならずに, 設定したComponent自身がresponderになることができる.
但し, 一般的なTouchableWithoutFeedbackなどではこの値が子要素に伝搬されていない為, 使うことができなかったりする.
記事が気に入ったらチップを送ることができます!
You can give me a cup of coffee :)
Kyash ID: soranoba
Amazon: Wish List
GitHub Sponsor: github.com/sponsors/soranoba
PayPal.Me: paypal.me/soranoba
(Updated: )