【问题标题】:How to capture all clicks outside of a React Native component?如何捕获 React Native 组件之外的所有点击?
【发布时间】:2018-09-29 04:37:05
【问题描述】:

我试图弄清楚如何捕获所有点击事件,以确定它们是否在我的 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>
        );
    }
}

【问题讨论】:

标签: javascript reactjs react-native


【解决方案1】:

您可以根据PanResponder查看点击次数。

PanResponder 包含here 中提到的方法。

但你只需要

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

这是简单示例

注意:您需要在Parent View上设置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>
    );
}

如果响应者的原生事件目标touchable的原生事件目标匹配,那么它是inside,否则是outside

【讨论】:

  • 我不太了解 PanResponder 但我不需要跟踪鼠标的移动我只需要知道点击的位置。我希望得到一个可以处理我的 hideSearchBar 功能的答案。我目前正在通过 TouchableWithoutFeedback 检测点击,但确定点击是否在某个组件(SearchBar)之外是我不明白该怎么做的。
  • 平移响应器是为您提供已被手势处理的视图的节点 ID,如果节点 ID 不是您的可触摸 ID,则它位于可触摸框之外。
  • 代码示例的哪一部分实际上是在进行评估以确定点击是否在外部??
  • 也许您需要添加onStartShouldSetResponderCapture。在开始触摸时调用onStartShouldSetResponderCapture ,每次移动手指时调用onMoveShouldSetResponderCapture
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-02
  • 1970-01-01
相关资源
最近更新 更多