1import React, { Component } from 'react'; 2import { StyleSheet, View, StyleProp, ViewStyle } from 'react-native'; 3import { 4 LongPressGestureHandler, 5 State, 6 TapGestureHandler, 7 LongPressGestureHandlerStateChangeEvent, 8 TapGestureHandlerStateChangeEvent, 9} from 'react-native-gesture-handler'; 10 11interface FBState { 12 singleTap?: State; 13 longPress?: State; 14} 15 16export default class FancyButton extends Component< 17 { 18 style?: StyleProp<ViewStyle>; 19 onLongPress?: () => void; 20 onSingleTap?: () => void; 21 onDoubleTap?: () => void; 22 children?: React.ReactNode; 23 }, 24 FBState 25> { 26 doubleTapRef = React.createRef<TapGestureHandler>(); 27 28 readonly state: FBState = {}; 29 30 render() { 31 return ( 32 <LongPressGestureHandler minDurationMs={800} onHandlerStateChange={this._onLongPressEvent}> 33 <TapGestureHandler 34 numberOfTaps={1} 35 waitFor={this.doubleTapRef} 36 onHandlerStateChange={this._onSingleTapEvent}> 37 <TapGestureHandler 38 numberOfTaps={2} 39 ref={this.doubleTapRef} 40 onHandlerStateChange={this._onDoubleTapEvent}> 41 <View 42 style={[styles.button, this.props.style, { opacity: this._isPressed() ? 0.5 : 1 }]}> 43 {this.props.children} 44 </View> 45 </TapGestureHandler> 46 </TapGestureHandler> 47 </LongPressGestureHandler> 48 ); 49 } 50 51 _isPressed = () => { 52 const { longPress, singleTap } = this.state; 53 54 // Intentionally leave out double tap 55 if (longPress === State.BEGAN || singleTap === State.BEGAN) { 56 return true; 57 } else { 58 return false; 59 } 60 }; 61 62 _onLongPressEvent = (event: LongPressGestureHandlerStateChangeEvent) => { 63 const { state } = event.nativeEvent; 64 this.setState({ longPress: state }); 65 66 if (state === State.ACTIVE) { 67 this.props.onLongPress && this.props.onLongPress(); 68 } 69 }; 70 71 _onSingleTapEvent = (event: TapGestureHandlerStateChangeEvent) => { 72 const { state } = event.nativeEvent; 73 this.setState({ singleTap: state }); 74 75 if (state === State.ACTIVE) { 76 this.props.onSingleTap && this.props.onSingleTap(); 77 } 78 }; 79 80 _onDoubleTapEvent = (event: TapGestureHandlerStateChangeEvent) => { 81 const { state } = event.nativeEvent; 82 83 if (state === State.ACTIVE) { 84 this.props.onDoubleTap && this.props.onDoubleTap(); 85 } 86 }; 87} 88 89const styles = StyleSheet.create({ 90 button: { 91 paddingHorizontal: 30, 92 paddingVertical: 20, 93 backgroundColor: '#cacaca', 94 borderRadius: 5, 95 alignItems: 'center', 96 }, 97}); 98