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>
);
}
}
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 moveonPanResponderTerminationRequest
: 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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With