React-native-gesture-handler: TouchableOpacity inside of TapGestureHandler

Created on 30 Apr 2019  路  7Comments  路  Source: software-mansion/react-native-gesture-handler

I have many components inside of one big container component that has a TapGestureHandler on it. For example:

import { TouchableOpacity } from 'react-native-gesture-handler'
public render() {
        return (
            <TapGestureHandler
                onHandlerStateChange={this._onSingleTap}
            >
                 <TouchableOpacity />
                 <TouchableOpacity />
            </TapGestureHandler>
        )
    }

The above example is a very basic one. In reality, my view is very complex and has many different TouchableOpacitys in addition to many TextInputs spanning across many wrapper components.

Currently, when tapping on one of the TouchableOpacitys, only TapGestureRecognizer.onHandlerStateChange is called. The exact opposite should happen, TouchableOpacity.onPress should get called and TapGestureRecognizer.onHandlerStateChange should NOT get called.

This is a very big issue for me, I would appreciate any help I can get! Has this been fixed in the upgrade branch?

Zach

Gesture handlers Important Touchable

Most helpful comment

is there any updates on this issue, facing the exact same one right now

All 7 comments

As a workaround you can write own TouchableOpacity based on TapGestureHandler and replace it in all places inside of your container. Anohter options - you can use react native PanResponder to handle this case (but if you have ScrollView inside of container you will face some issues on IOS).

@zsaraf did you find a solution for this?

@Chehow , can you explain a bit more on how you can solve this with a custom TouchableOpacity? I have tried this concept, but when I nest them, tapping on a nested one, still triggers both the nested handler, and the container handler.

@curiousdustin basically we did something like this:

class TouchableOpacity extends Component<TouchableOpacityProps, any> {

    private opacityValue: Animated.Value<number> = new Animated.Value(1);
    private opacityClock = new Animated.Clock();

    gestureEvent(e) {
        if (e.nativeEvent.state == State.END) {
            this.opacityValue.setValue(.2);
            if (this.props.onPress) {
                this.props.onPress();
            }
        }
    }

    render() {
        return (
            <TapGestureHandler key={this.props.key} onHandlerStateChange={e => this.gestureEvent(e)}>
                <Animated.View style={[
                    this.props.style,
                    {
                        opacity: cond(
                            neq(this.opacityValue, 1),
                            block([
                                set(this.opacityValue, AnimationHelper.runTimingAnimation(this.opacityClock, this.opacityValue, 1, 300)),
                            ]),
                            1
                        )
                    }
                ]}>
                    {this.props.children}
                </Animated.View>
            </TapGestureHandler>
        )
    }
}

Not perfect, but seems to work fine so far.

is there any updates on this issue, facing the exact same one right now

Did anyone get any precise and simple solution for this ?

Try putting each TouchableOpacity inside a TapGestureHandler

            <TapGestureHandler
                onHandlerStateChange={this._onSingleTap}
            >
                //.....
                  <TapGestureHandler>
                        <TouchableOpacity />
                  <TapGestureHandler/>
                  <TapGestureHandler>
                        <TouchableOpacity />
                  <TapGestureHandler/>
                //.....
            </TapGestureHandler>
Was this page helpful?
0 / 5 - 0 ratings

Related issues

tallen11 picture tallen11  路  3Comments

wcandillon picture wcandillon  路  4Comments

brentvatne picture brentvatne  路  4Comments

jacobrosenskold picture jacobrosenskold  路  3Comments

neiker picture neiker  路  3Comments