Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to capture all clicks outside of a React Native component?

I am trying to figure out how I can capture all click events to determine if they were clicked outside of my SearchBar drop down menu. If so then the drop down menu will close. I have a way of detecting all click events (TouchableWithoutFeedback) but I am not able to figure out a way to compare or determine if it was outside of my component or not. Anyone know how to do this in React Native??

class Products extends Component {

    constructor(props) {
        super(props);

        this.hideSearchBar = this.hideSearchBar.bind(this);
    }

    hideSearchBar(e) {
        console.log('e: ', e.nativeEvent.target)
        // Determine if the click event was outside of the SearchBar component
    }

    render() {
        const {isLoading, products} = this.props.products;

        return (
            <TouchableWithoutFeedback onPress={(e) => this.hideSearchBar(e)} style={{zIndex: 0}}>
                <View style={styles.wrapper}>
                    <Header/>
                    <View style={styles.bodyWrapper}>
                        <ScrollView style={styles.scrollView}>
                            <ProductsContainer data={{productsList: { results: products }}}/>
                        </ScrollView>
                        <SearchBar ref={node => this.node = node} style={styles.searchBar}/>
                    </View>
                    <Footer/>
                </View>
            </TouchableWithoutFeedback>
        );
    }
}
like image 685
FairyQueen Avatar asked Apr 18 '18 20:04

FairyQueen


1 Answers

You can check the clicks based on the PanResponder.

PanResponder contains the methods as mentioned here.

But you only need

  • onMoveShouldSetPanResponderCapture: To set the capture of movement of the interaction.
  • onPanResponderMove: To capture the events on move
  • onPanResponderTerminationRequest: Terminate responder if other resource requires access to it.

Here's the simple example

Note: You need to set the PanResponder Handler on the Parent View to access the touch events in the whole screen.

const touchThreshold = 20;

state = {
        outsideTarget: null,
    }

componentWillMount () {
        this._panResponder = PanResponder.create({   //...Create the Responder
            // Ask to be the responder:
             // Ask to be the responder:
        onMoveShouldSetPanResponderCapture: (evt, gestureState) => {
            const {dx, dy} = gestureState;

            return (Math.abs(dx) > touchThreshold) || (Math.abs(dy) > touchThreshold);
        },
            onPanResponderMove: (evt, gestureState) => {
                console.log('Responder' + evt.nativeEvent.target)
                this.setState({outsideTarget: true})
                // The most recent move distance is gestureState.move{X,Y}

                // The accumulated gesture distance since becoming responder is
                // gestureState.d{x,y}
            },
            onPanResponderTerminationRequest: (evt, gestureState) => true,

        });
    }

componentDidUpdate(prevProps, prevState, snapshot) {
       if(this.state.outsideTarget) {
            Alert.alert('Success', 'Component Clicked OutSide')
        } else if(!this.state.outsideTarget) {
           Alert.alert('Success', 'Component Clicked Inside')

       }
    }


 hideSearchBar(e) {
    // Determine if the click event was outside of the SearchBar component
    this.setState({outsideTarget: false})
}

render() {
    return (
        <View style={{flex: 1}}  {...this._panResponder.panHandlers}> //...Set the responder to the parent view
            <TouchableOpacity  onPressIn={(e) => this.hideSearchBar(e)} style={{height: 100, width: 100, backgroundColor: 'red'}} />
        </View>
    );
}

If the responder's native event target matches the touchable's native event target then it is inside, else outside

like image 74
Pritish Vaidya Avatar answered Sep 28 '22 07:09

Pritish Vaidya