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

onScrollBegin triggers on single tap but onScrollEnd does not #244

Open
andonovn opened this issue Aug 26, 2022 · 10 comments
Open

onScrollBegin triggers on single tap but onScrollEnd does not #244

andonovn opened this issue Aug 26, 2022 · 10 comments
Assignees
Labels
bug Something isn't working

Comments

@andonovn
Copy link

Hey there, thanks for the nice library ^^

I think the behaviour for onScrollBegin and onScrollEnd should be the same once a user do a single tap on the carousel. Currently, the first one gets executed while the latter is not.

To Reproduce
Steps to reproduce the behavior:

  1. Load the Carousel with required data
  2. Add onScrollBegin={() => console.log('start')} onScrollEnd={() => console.log('end')}
  3. Tap on the Carousel
  4. See 'start' but not 'end'

Expected behavior
Either both callbacks should be executed, OR neither of the callbacks should not be executed

Versions (please complete the following information):

  • react: v17.0.2
  • react-native: v0.68.2
  • react-native-reanimated: v2.8.0
  • react-native-reanimated-carousel: v3.0.4
  • react-native-gesture-handler: v2.2.1

Smartphone (please complete the following information):

  • Device: iPhone 13 Pro
  • OS: 15.1

Haven't tested on other devices, my blind guess is it will work the same across all the devices but I may be terribly wrong :)

Not sure if this is considered a bug but in our case it is because we use the both callbacks to toggle absolutely positioned elements on the screen, outside the Carousel. Any suggestions for work-arounds are welcomed ^^

@andonovn andonovn added the bug Something isn't working label Aug 26, 2022
@dohooo
Copy link
Owner

dohooo commented Aug 26, 2022

Thanks for your detailed reproduction. I'll check it ASAP
.

@sylvaindubus
Copy link

Same issue here. :(
Did you find any workaround @andonovn?

@sylvaindubus
Copy link

I've managed to reproduce the same behavior using onProgressChange:

const [scrolling, setScrolling] = useState(false);

useEffect(() => {
  if (scrolling) {
    // do onScrollBegin stuff
  } else {
    // do onScrollEnd stuff
  }
}, [scrolling]);


const onProgressChange = (_: number, absoluteProgress: number) => {
  if (absoluteProgress % 1 !== 0) {
    setScrolling(true);
  } else {
    setScrolling(false);
  }
}; 

@martwetzels
Copy link

I'm experiencing this issue as well, for context see SO, where the onScrollBegin and onScrollEnd are used to prevent Pressable child components from being triggered. The onScrollBegin gets triggered at a single tap (expected gesture for Pressing) instead of at actually scrolling (swiping gesture) the carousel.

@davidwagn
Copy link

@martwetzels

This is the exact issue I'm having (even came from the same SO question). Did you end up finding a solution?

@martwetzels
Copy link

@davidwagn not with this library, I ended up implementing something myself that got the job done.

@Vepsur
Copy link

Vepsur commented Jan 3, 2023

Same issue :( Any solutions?

@AlexanderCollins
Copy link

I'm not sure if this is entirely related, maybe I've missed the point of this thread. My issue was with being able to detect when a user taps a child of the carousel vs swiping through the carousel itself... I wanted to at least put this here to help anyone that needs a solution in the mean time even if it's not ideal...

I ended up having to use state to track when a child item is pressed and checked the change in x movement on the onPressOut event to be able to detect pressing children vs swiping through the carousel...

const MyComponent = () => {
    const [pressState, setPressState] = useState({});
    return (
        <Carousel
            ...
            renderItem={({ index }) => (
                <Pressable
                  onPressIn={(event) => {   
                    setPressState({
                      ...pressState,
                      [index]: event.nativeEvent.pageX,
                    });
                  }}
                  onPressOut={(event) => {
                    const delta = event.nativeEvent.pageX - pressState[index] || 0;
                    if (Math.abs(delta) < 5) {
                      // handle item pressed here
                    }
                  }}
                  key={index}
                >
                  {/* Child Item */}
                </Pressable>
              )}
        />
    )
}

@ajp8164
Copy link

ajp8164 commented Jan 20, 2023

I'm experiencing the same/similar issue. I'm not using onScrollBegin or onScrollEnd but on app launch the first attempt to swipe the carousel left/right results in the child (card) receiving a touch event. This only happens on first swipe try after launch. It never happens again until next app launch.

Here's my carousel. The presence of onProgressChange does not make a difference.

      <Carousel
        ref={carouselRef}
        data={cards}
        renderItem={renderCard}
        loop={false}
        width={viewport.width}
        style={{ overflow: 'visible' }}
        onProgressChange={() => {
          if (carouselRef.current) {
            const currentSlide = carouselRef.current.getCurrentIndex();
            if (currentSlide !== activeSlideRef.current) {
              activeSlideRef.current = currentSlide;
              onScrollIndexChanged(currentSlide);
            }
          }
        }}
      />

@MatLish00010
Copy link

MatLish00010 commented Aug 22, 2023

const animationState = useRef({ shouldBeFinished: false, started: false, });

  <Carousel
    ....
    onScrollEnd={() => {
    if (animationFinished && animationStarted) {
      animationState.current.shouldBeFinished = true;
    }
  }}
  onProgressChange={() => {
    if (animationFinished && animationStarted) {
      if (animationState.current.shouldBeFinished) {
        animationFinished();
        animationState.current.shouldBeFinished = false;
        animationState.current.started = false;
      } else if (!animationState.current.started) {
        animationStarted();
        animationState.current.started = true;
      }
    }
  }}
  />

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

9 participants