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>
);
}
↓ こんな感じです。