React Native / 複数要素の同時タップをハンドリングしたい時

ボタン2つ押したら何かする、みたいな時です。

Touchable

TouchableHighlight は同時に2つタップするということができないみたい。
片方タップしたらもう片方は反応しなかった。

jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class MyComponent extends Component {

  constructor(props) {
    super(props);
    this.state = { text1: 'text 1', text2: 'text 2', text3: 'text 3' };
  }

  render() {
    return (
      <View>
        <TouchableHighlight onPress={() => { this.setState({ text1: 'touch started' }); }}>
          <Text>{this.state.text1}</Text>
        </TouchableHighlight>
        <TouchableHighlight onPress={() => { this.setState({ text2: 'touch started' }); }}>
          <Text>{this.state.text2}</Text>
        </TouchableHighlight>
      </View>
    );
  }
}

export default JobSearch;

View with Responder

Touchable ... のかわりに View を使って適切に Responder を設定する。
Touchable は複雑なレスポンダーの設定をやってくれているので便利だが、いろいろやりたい場合は自分で設定するしかない。
Gesture Responder System

TouchableHighlight and Touchable*
The responder system can be complicated to use. So we have provided an abstract Touchable implementation for things that should be "tappable". This uses the responder system and allows you to easily configure tap interactions declaratively. Use TouchableHighlight anywhere where you would use a button or link on web.

jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
render() {
  return (
    <View
      style={{ padding: 20 }}
      onStartShouldSetResponder={() => true}
      onResponderGrant={() => { this.setState({ text1: 'touch started' }); }}
      onResponderReject={() => { this.setState({ text1: 'touch started' }); }}
      onResponderRelease={() => { this.setState({ text1: 'text 1' }) }}
    >
      <Text>{this.state.text1}</Text>
    </View>

    <View
      style={{ padding: 20 }}
      onStartShouldSetResponder={() => true}
      onResponderGrant={() => { this.setState({ text2: 'touch started' }); }}
      onResponderReject={() => { this.setState({ text2: 'touch started' }); }}
      onResponderRelease={() => { this.setState({ text2: 'text 2' }); }}
    >
      <Text>{this.state.text2}</Text>
    </View>
  );
}

これで行けるだろうと思ったのですが、うまいこと行きません。。
onResponderReject は他の要素がアクティブで、タップが受け付つけられなかった時に発火するはずなのですが…

仕方がないので onTouchStart とかにしたらひとまず反応しました。
onTouchStart ってドキュメントには載ってないんだけどな…

jsx
1
2
3
4
5
6
7
8
9
10
11
12
render() {
  return (
    // ... 省略
    <View
      style={{ padding: 20 }}
      onTouchStart={() => { this.setState({ text3: 'touch started' }); }}
      onTouchEnd={() => { this.setState({ text3: 'text 3' }); }}
    >
      <Text>{this.state.text3}</Text>
    </View>
  );
}

↓ こんな感じです。

何かありましたらコメントをどうぞ

comments powered by Disqus

人気の記事

950 Points チリ出身のギタリストが弾くドラゴンボールZがむちゃくちゃかっこいい…
774 Points Wordpress + Heroku + PostgreSQL + Amazon S3 = ¥0 / 無料でサイト運営
700 Points Rubyのチートシート 変数 / クラス / モジュール
524 Points Rubyのチートシート / アクティブサポート
451 Points 紙のデザイナーがウェブ開発できるようになるまでに必要なこと
435 Points Rails / Google Analyticsのデータを使って分析や管理画面のためのグラフをつくる
323 Points RailsとHerokuでノーティフィケーションをプッシュする / PusherとTurbolinksの兼ね合い
222 Points Rails / RSpec テスト書いたことない メンドクサイ(n´Д`)という時のチートシート
193 Points Rails / Ajaxを使って画面遷移しない一時保存機能をつける
193 Points Protractorでスクレイピングしてみた