Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PanResponder could not detect touch if i touch on Touchables(TouchableHighlight, TouchableOpacity, TouchableWithoutFeedback)

Tags:

react-native

I have implemented PanResponder in my project but it only works when I touch non touchable elements . When I touch touchable elements like TouchableOpacity, PanReponder does not responds.But when I move my finger on TouchableOpacity PanResponder responds.

Same thing happening for Button also

Please tell me what might be the problem.

Expo Link : https://snack.expo.io/SyYrtq87W

import React, { Component } from 'react';
import { Button, PanResponder, View, StyleSheet,TouchableOpacity } from 'react-native';
import { Constants } from 'expo';

export default class App extends Component {
  state = {
    show : false
  };
  _panResponder = {};

  componentWillMount() {
    this._panResponder = PanResponder.create({

      onStartShouldSetPanResponder: () => {
        alert('clicked')
        console.log('clicked')
        return true
      },
      onMoveShouldSetPanResponder: () => {
        alert('moved')
        console.log('moved')
        return true
      },
      onStartShouldSetPanResponderCapture: () => false,
      onMoveShouldSetPanResponderCapture: () => false,
      onPanResponderTerminationRequest: () => true,
      onShouldBlockNativeResponder: () => false,
    });
  }

  render() {
    return (
      <View
        style={styles.container}
        collapsable={false}
        {...this._panResponder.panHandlers}>

 {/*********************PanResponder does not respond***************************/}       

        <TouchableOpacity>
          <View style={{width:200, height:200,backgroundColor:'red'}}>
          </View>
        </TouchableOpacity>



        <Button
          title="Here is a button for some reason"
          onPress={() => {}}  
        />

  {/*****************************************************************************/}
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    paddingTop: Constants.statusBarHeight,
    backgroundColor: '#ecf0f1',
  }
});
like image 304
tonysta Avatar asked Dec 04 '22 22:12

tonysta


2 Answers

I had a similar issue. Basically because you always return true in onStartShouldSetPanResponder and/or onMoveShouldSetPanResponder they will take command over that touch event.

My workaround: Don't consider the touch "yours" (PanResponder's) unless the user moved it a little first by a threshold you set.

const touchThreshold = 20;
const panResponder = PanResponder.create({
    onStartShouldSetPanResponder : () => false,
    onMoveShouldSetPanResponder : (e, gestureState) => {
        const {dx, dy} = gestureState;

        return (Math.abs(dx) > touchThreshold) || (Math.abs(dy) > touchThreshold);
    },
    ...
});
like image 187
Moti Azu Avatar answered Jan 11 '23 23:01

Moti Azu


Finally It hit me. It was a very silly mistake. forgot to add alert('clicked') at

onStartShouldSetPanResponderCapture: ()

Now,

onStartShouldSetPanResponderCapture: () => {alert('clicked') ; return false},

Expo Link : https://snack.expo.io/ryWx7lBrb

Now, it takes touch everywhere, including Touchables and Buttons.

import React, { Component } from 'react';
import { Button, PanResponder, View, StyleSheet,TouchableOpacity } from 'react-native';
import { Constants } from 'expo';

export default class App extends Component {
  state = {
    show : false
  };
  _panResponder = {};

  componentWillMount() {
    this._panResponder = PanResponder.create({

      onStartShouldSetPanResponder: () => {
        alert('clicked')
        return true
      },
      onMoveShouldSetPanResponder: () => true,
      onStartShouldSetPanResponderCapture: () => {alert('clicked') ; return false},
      onMoveShouldSetPanResponderCapture: () => false,
      onPanResponderTerminationRequest: () => true,
      onShouldBlockNativeResponder: () => false,
    });
  }

  render() {
    return (
      <View
        style={styles.container}
        collapsable={false}
        {...this._panResponder.panHandlers}>

 {/*********************PanResponder now responds***************************/}       

        <TouchableOpacity>
          <View style={{width:200, height:200,backgroundColor:'red'}}>
          </View>
        </TouchableOpacity>



        <Button
          title="Here is a button for some reason"
          onPress={() => {}}  
        />

  {/*****************************************************************************/}
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    paddingTop: Constants.statusBarHeight,
    backgroundColor: '#ecf0f1',
  }
});
like image 45
tonysta Avatar answered Jan 12 '23 01:01

tonysta