👆

React Native Gesture Handler が持つ機能を紹介する

2022/01/13に公開

はじめに

私は主に React Native を使ってモバイルアプリ開発をしています。
React Native でよく使われるライブラリの一つに React Native Gesture Handler があります。
他のライブラリから参照されていることも多く、主要なところでは画面遷移ライブラリの React Navigation でも使われているため、知らず知らずのうちに自分のプロジェクトも参照しているということも多いんじゃないかなと思います。

私が普段開発しているアプリでも別のライブラリが必要とする関係で Gesture Handler を導入していたのですが、「こいつはナニができるの?🤔」といった調子で恥ずかしながら意味がわかっていませんでした。
この度、あるきっかけ(そうです、不具合です)で必要に駆られて調べたので忘れないように記事にまとめることにしました。

主要な機能

Gesture Hanlder が提供する機能には以下のようなものがあります。

  • ネイティブのハンドリングシステムを使って、pinch, rotation, pan などのジェスチャーを制御可能にする
  • ジェスチャーハンドラ同士の関係性を定義する機能

Gesture Handler には1系と2系の二つのバージョンがありますが、ここで紹介する機能はどちらのバージョンにも共通する機能です。

ネイティブのハンドリングシステムを使う

まずは簡単に、素の React Native のタッチイベントハンドリングシステムを紹介したいと思います。
素の React Native ではボタンなどのタッチ操作を JavaScript によるハンドリングシステムで実現しています。

(注釈)上記画像は Gesture Handler 作者の @kzzzf さんによるこちらの登壇映像からお借りしました。

しかし、全てのタッチ操作をこのJSによるシステムで制御しているわけではなく、例えば ScrollView の挙動はネィティブに任せています。ネィティブで動作するということは、JSスレッドではなくUIスレッド上で実行されるということです。

このようなシステムでは以下のような問題が生じます。

  • ジェスチャーを制御するロジックがUIスレッドとJSスレッドの両方に分散してしまい、挙動が予測しにくい
  • JSスレッドでジェスチャーを制御する場合は、画面が滑らかに更新されないといったパフォーマンスの問題が起きやすい

そこで、Gesture Handler では JS によるハンドリングシステムを 使わず に、ネィティブで制御できるようにすることで上記問題の解消を図っています。

ジェスチャーハンドラ同士の関係性

もう一度 @kzzzf さんのスライドをお借りします。

上の画像のように、ドロワーの中にスライダーがあるUIがあるとします。スライダーを左右に動かした時は、ドロワーは開かれたままスライダーだけが動いて欲しいと思います。一方で、スライダー部分ではないところをタップして左右に動かした時は、ドロワーが左右に動いて欲しいです。
このように、複数のUIコンポーネントが協調してタッチイベントを処理して欲しいケースはあると思います。
Gesture Handler では別のコンポーネントがイベントをハンドリングしない場合だけ、自分のハンドラを実行する、といった協調関係を定義することができます。

終わりに

この記事を書くにあたっては、 Gesture Handlerのドキュメント 及び、作者の @kzzzf さんが発表したトーク映像 を大いに参考にさせていただきました。

私の記事が不明瞭な箇所については、これらの資料を見ていただければ解決するはずです。偉大なライブラリを作ってくれた作者に感謝🙏

Discussion