Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

onPanResponderTerminationRequest is not called on Android #27778

Closed
delanebob opened this issue Jan 15, 2020 · 2 comments
Closed

onPanResponderTerminationRequest is not called on Android #27778

delanebob opened this issue Jan 15, 2020 · 2 comments
Labels
API: PanResponder Bug Platform: Android Android applications. Stale There has been a lack of activity on this issue and it may be closed soon.

Comments

@delanebob
Copy link

React: 16.9.0
React Native version: 0.61.4 (through expo v36.0.1)
Android Version: 9

I've created a Swipe component (code shared below) using the PanResponder. The onPanResponderTerminationRequest method returns false to fix a bug that was causing the swipe to be unexpectedly interrupted and terminate earlier than expected.

This fix worked perfect on iOS, but it didn't work on Android. I noticed that even though the onPanResponderTerminate was getting called, onPanResponderTerminationRequest never seemed to get called on Android.

I have looked at the documentation and it doesn't mention anything about it only working for iOS and in my research, I haven't found any explanation for this.

I found these old issues reporting the same thing, but all were just closed with no resolution or explanation.

Steps To Reproduce

  1. Wrap Swipe component around ScrollView
  2. Add some content into the ScrollView so you can swipe and sometimes see that onPanResponderTerminate.
  3. Check onPanResponderTerminationRequest to see if it's called using a console.log
  4. You'll notice on iOS the console.log is called, but on Android it's not.

Describe what you expected to happen:
Before onPanResponderTerminate is called onPanResponderTerminationRequest should be called on both iOS and Android

Swipe.js

import React, { useCallback, useMemo, useState } from 'react';
import {
  PanResponder, Animated,
} from 'react-native';
import PropTypes from 'prop-types';
import get from 'lodash/get';

const Swipe = props => {
  const [width, setWidth] = useState(0);
  const [containerTranslateX] = useState(new Animated.Value(0));

  const handleSetWidth = useCallback(e => setWidth(get(e, 'nativeEvent.layout.width', 0)), []);

  const dragOffsetForTransparency = useMemo(() => 0.6 * width, [width]);

  const panResponder = PanResponder.create({
    onStartShouldSetPanResponder: () => false,
    onMoveShouldSetPanResponder: (e, { dx, dy }) => {
      const isPanned = Math.abs(dx) > 4;
      const isSwipedRatherThenScrolled = Math.abs(dx) > Math.abs(dy);

      if (isPanned && isSwipedRatherThenScrolled) {
        props.onSwipeStart();
        return true;
      }

      return false;
    },
    onPanResponderMove: Animated.event([null, {
      dx: containerTranslateX,
    }]),
    onPanResponderEnd: (e, { dx, vx }) => {
      if ((Math.abs(dx) / width > props.threshold) || (Math.abs(vx) > 0.7)) { /* eslint-disable-line */
        if (dx > 0) {
          Animated.spring(containerTranslateX, { toValue: width, friction: 1000, overshootClamping: true }).start();
          Animated.timing(containerTranslateX, { toValue: -width, duration: 0 }).start();
          Animated.spring(containerTranslateX, { toValue: 0, friction: 1000, overshootClamping: true }).start();
          props.onSwipeRight();
        } else {
          Animated.spring(containerTranslateX, { toValue: -width, friction: 1000, overshootClamping: true }).start();
          Animated.timing(containerTranslateX, { toValue: width, duration: 0 }).start();
          Animated.spring(containerTranslateX, { toValue: 0, friction: 1000, overshootClamping: true }).start();
          props.onSwipeLeft();
        }
      } else {
        Animated.spring(containerTranslateX, { toValue: 0 }).start();
      }
      props.onSwipeEnd();
    },
    onPanResponderTerminationRequest: () => false,
  });

  return (
    <Animated.View
      onLayout={ handleSetWidth }
      { ...panResponder.panHandlers }
      style={{
        flexGrow: 1,
        opacity: containerTranslateX.interpolate({
          inputRange: [-dragOffsetForTransparency, 0, dragOffsetForTransparency],
          outputRange: [0, 1, 0],
        }),
        transform: [{ translateX: containerTranslateX }],
      }}>
      { props.children }
    </Animated.View>
  );
};

Swipe.propTypes = {
  threshold: PropTypes.number,
  onSwipeLeft: PropTypes.func.isRequired,
  onSwipeRight: PropTypes.func.isRequired,
  onSwipeStart: PropTypes.func,
  onSwipeEnd: PropTypes.func,
};

Swipe.defaultProps = {
  threshold: 0.4,
  onSwipeStart: () => {},
  onSwipeEnd: () => {},
};

export default Swipe;

Sample of file using Swipe.js

import React, {
  useState,
} from 'react';
import {
  ScrollView,
  View,
} from 'react-native';

const SampleComponent = props => {
  const [isSwipingView, setIsSwipingView] = useState(false);
  
  return (
    <ScrollView
      scrollEnabled={ !isSwipingView }
    >
      <Swipe
        onSwipeLeft={ () => { /* do something when swipe right */ } }
        onSwipeRight={ () => { /* do something when swipe right */ } }
        onSwipeStart={ () => setIsSwipingView(true) }
        onSwipeEnd={ () => setIsSwipingView(false) }
      >
        <View>
          {/* View with content in it */}
        </View>
      </Swipe>
    </ScrollView>
  );
};

export default SampleComponent;
@stale
Copy link

stale bot commented Apr 14, 2020

Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. You may also label this issue as a "Discussion" or add it to the "Backlog" and I will leave it open. Thank you for your contributions.

@stale stale bot added the Stale There has been a lack of activity on this issue and it may be closed soon. label Apr 14, 2020
@stale
Copy link

stale bot commented Apr 21, 2020

Closing this issue after a prolonged period of inactivity. If this issue is still present in the latest release, please feel free to create a new issue with up-to-date information.

@stale stale bot closed this as completed Apr 21, 2020
@facebook facebook locked as resolved and limited conversation to collaborators Apr 22, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
API: PanResponder Bug Platform: Android Android applications. Stale There has been a lack of activity on this issue and it may be closed soon.
Projects
None yet
Development

No branches or pull requests

2 participants