如何捕获 React Native 组件之外的所有点击?

Fai*_*een 6 javascript reactjs react-native

我想弄清楚如何捕获所有点击事件以确定它们是否在我的 SearchBar 下拉菜单之外被点击。如果是这样,则下拉菜单将关闭。我有一种检测所有点击事件的方法(TouchableWithoutFeedback),但我无法找到一种方法来比较或确定它是否在我的组件之外。有人知道如何在 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>
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

Pri*_*dya 3

您可以根据PanResponder检查点击情况。

PanResponder包含此处提到的方法。

但你只需要

  • onMoveShouldSetPanResponderCapture:设置交互动作的捕捉。
  • onPanResponderMove:捕捉移动中的事件
  • onPanResponderTerminationRequest:如果其他资源需要访问响应程序,则终止响应程序。

这是一个简单的例子

注意:您需要在父视图PanResponder Handler上设置才能访问整个屏幕的触摸事件。

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>
    );
}
Run Code Online (Sandbox Code Playgroud)

如果响应者的本机事件目标与可触摸对象的本机事件目标匹配,则它位于inside,否则位于 Outside