Robert Clouth
Robert Clouth

Reputation: 316

Multiple gesture responders at the same time

I need some buttons that can be pressed at the same time, but currently if you press one, it 'claims' responsiveness and the others can't be pressed anymore. How do I do this?

Upvotes: 5

Views: 1186

Answers (2)

Tushar Shahi
Tushar Shahi

Reputation: 20676

After the introduction of react-native-gesture-handler it can be done quite easily.

Firstly we need our button components to be descendants of GestureHandlerRootView, so wrap the tree in it.

Now, use the GestureDetector to wrap your buttons:

const MutliTapAllowButton = ({ children, callback }) => {
    const tap = Gesture.Tap()
    .runOnJS(true) // should work without this too
    .onBegin(callback)

    return <GestureDetector gesture={tap}>{children}</GestureDetector>
}

Upvotes: 0

Robert Clouth
Robert Clouth

Reputation: 316

Got it. You have to use ReactNativeEventEmitter to directly listen to touch events and bypass the Gesture Responder stuff entirely. Below is a decorator class that calls onTouchStart, onTouchEnd and onTouchMove in the wrapped class whenever those touch events are received.

'use strict';

import React, {Component} from 'react-native';
import ReactNativeEventEmitter from 'ReactNativeEventEmitter';
import NodeHandle from 'NodeHandle';

export const multitouchable = BaseComponent => {
    return class extends Component {

        constructor(props, context) {
            super(props, context);

            this.comp = null;
            this.compId = null;
        }

        componentDidMount() {
            if(this.comp && this.compId){
                this.comp.onTouchStart && ReactNativeEventEmitter.putListener(this.compId, 'onTouchStart', e => this.comp.onTouchStart(e));
                this.comp.onTouchEnd && ReactNativeEventEmitter.putListener(this.compId, 'onTouchEnd', e => this.comp.onTouchEnd(e));
                this.comp.onTouchMove && ReactNativeEventEmitter.putListener(this.compId, 'onTouchMove', e => this.comp.onTouchMove(e));
            }
        }

        componentWillUnmount() { 
            if(this.comp && this.compId){
                this.comp.onTouchStart && ReactNativeEventEmitter.deleteListener(this.compId, 'onTouchStart');
                this.comp.onTouchEnd && ReactNativeEventEmitter.deleteListener(this.compId, 'onTouchEnd');
                this.comp.onTouchMove && ReactNativeEventEmitter.deleteListener(this.compId, 'onTouchMove');
            }
        }

        render() {
            return (
                <BaseComponent {...this.props} {...this.state}
                    ref={c => {
                        this.comp = c;
                        const handle = React.findNodeHandle(c);
                        if(handle)
                            this.compId = NodeHandle.getRootNodeID(handle);
                    }}
                />
            );
        }
    };
}

Upvotes: 1

Related Questions