0
Help us understand the problem. What are the problem?

posted at

updated at

【ReactNative】FlatList自体のタップを判別する

目次

1.やりたいこと
2.起きていた問題
3.原因
4.解決策
5.まとめ

1. やりたいこと

赤枠内の青の部分を「タップした時だけ」イベントを発火させたい
スクロールされた場合はタップと判定したくない
青部分をタップしたときにキーボードを非表示にするという処理をしたい。

2. 起きていた問題

FlatListのonPressやonTouchEndやonTouchStartを使用して、
普通にタップのイベントを拾い処理を行おうとしたが、
単純に上記イベントを契機とするとスクロールした際にもイベントが発火してしまう問題が発生していました。

3. 原因

おそらくFlatList自体をタップした際のことは考えらておらず、
onpressとスクロールを判別するすべはReactNative API上にはない。
そのため自前でonPressとScrollの判定を行う.

4. 解決策

そのため、スクロールとタップの挙動の違いである
下記をもとにタップ判定をすることを考えた。

①タップ開始位置と終了位置 スクロール→違う タップ→ほぼ同じ
②タップ時間の長さ スクロール→長い タップ→短い

今回は①の違いを利用してX, Yの座標が同じであれば、
タップと判定する。それ以外はタップではないと判定する。

  onTouchStart = ({nativeEvent}) => {
    const { locationX, locationY } = nativeEvent
    this.setState({ locationX, locationY  })
  }
  onTouchEnd = ({nativeEvent}) => {
    const { locationX, locationY } = nativeEvent
    if(this.state.locationX == locationX && this.state.locationY == locationY){
      this.hideKeyboard(this.props)
    }
  }

<FlatList data={data}
    onTouchStart={this.onTouchStart}
    onTouchEnd={this.onTouchEnd}
    renderItem={this.renderItem}/>

最初は上記のコードだったが、
スマホによっては、性能がよくない場合があり、
図らずもタップがずれてしまうこともあるので、
余白を追加する。
今回は半径8pxの範囲未満であれば、タップと認識するようにした。

/**
   * タップ開始時と終了時の座標が半径8px以内に収まっていればタップとして認識する
   * タップの場合、キーボードをOFFにする
   */
  const ACCEPTBALE_LOCATION_GAP = 8

  onTouchStart = ({nativeEvent}) => {
    const { locationX, locationY } = nativeEvent
    this.setState({ locationX, locationY  })
  }
  onTouchEnd = ({nativeEvent}) => {
    const { locationX, locationY } = nativeEvent
    if(this.state.locationX - ACCEPTBALE_LOCATION_GAP < locationX && locationX < this.state.locationX + ACCEPTBALE_LOCATION_GAP
        && this.state.locationY - ACCEPTBALE_LOCATION_GAP < locationY && locationY < this.state.locationY + ACCEPTBALE_LOCATION_GAP){
      this.hideKeyboard()// ex. Keyboard OFFの処理
    }
  }

<FlatList data={data}
    onTouchStart={this.onTouchStart}
    onTouchEnd={this.onTouchEnd}
    renderItem={renderItem}/>

5. まとめ

ものすごく単純な処理で終わると思いきや、
ひと工夫する必要があった。
あまり調べた際に参考資料が出てこなかったので、
この記事を作成しました。
もっといいやり方があるよ!などあればぜひコメントまで!

では!

gamba!公式サイトはこちらへ! 《無料で15日間gamba!お試しできます》

株式会社gamba! カスタマーサクセスチーム note

gamba! 公式 facebookページ

gamba! 公式Twitter

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
0
Help us understand the problem. What are the problem?