最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

react native - Flatlist scrolling stealing Pan Gesture? - Stack Overflow

programmeradmin2浏览0评论

I have an Animated Flashlist created using Reanimated:-

import Reanimated from 'react-native-reanimated' 
const AnimatedFlashlist = Reanimated.createAnimatedComponent(FlashList);

The renderItem of this Flashlist contains 5 views in a row. Among those, two views are supposed to be draggable. It looks mostly like this:-

<View1></View1>
<DraggableView1></DraggableView1>
<View2></View2>
<DraggableView2></DraggableView2>
<View3></View3>

There are about 70 elements in the Flashlist.

Now, each draggable view is wrapped with a GestureDetector taken from react-native-gesture-handler

<GestureDetector gesture={dragGesture}>
    <SomeJSX/>
</GestureDetector>

What is the dragGesture assigned to it?

  • It is a Gesture.Pan() with its own onStart, onBegin, onEnd

Each DraggableView is wrapped with its own instance of Gesture.Pan() That's because each view should be draggable on its own.

The GestureHandlerRootView has been wrapped over the entire app.

What is the issue that I am facing?

  • I am supposed to implement auto scrolling when I drag one of the views reaches the top edge or bottom edge of the screen.
  • However, even though the scrolling starts, after some time, I lose access to the Pan Gesture and none of the onEnd or onFinalize gets called.
  • This doesn't happen at the starting of the auto scroll. It happens after auto scroll has happened 3 to 4 times

How am I auto scrolling?

const scrollFlatList = (cur: number, direction: 'up' | 'down') => {
    const offsetChange = 20;
    const newOffset = direction === 'up' ? cur - offsetChange : cur + offsetChange;
    flatListRef.current?.scrollToOffset({ offset: newOffset, animated: true });
};
const shouldAutoScroll = useDerivedValue(() => {
    const isDraggingActive = isDragging.value;
    const isAtTopEdge = dragY.value < SCROLL_THRESHOLD + 30;
    const isAtBottomEdge = dragY.value > height - SCROLL_THRESHOLD;
    return isDraggingActive && (isAtTopEdge || isAtBottomEdge);
});

useDerivedValue(() => {
    if (!shouldAutoScroll.value) {
        return;
    }

    const now = Date.now();
    if (now - lastScrollTime.value < 300) {
        return; // Prevent scrolling too frequently (every 300ms)
    }
    lastScrollTime.value = now;
    // let targetOffset;
    if (dragY.value > height - SCROLL_THRESHOLD) {
        scrollTarget.value = scrollOffset.value + 20;
        runOnJS(scrollFlatList)(scrollTarget.value, 'down');
    } else if (dragY.value < SCROLL_THRESHOLD + 30) {
        scrollTarget.value = scrollOffset.value - 20;
        runOnJS(scrollFlatList)(scrollTarget.value, 'up');
    } else {
        // runOnJS(stopScrolling)();
    }
});

My dragGesture looks mostly like this and I am updating the dragY value in onUpdate. dragY is a shared value. I am keeping all calculations on UI thread

Gesture.Pan()
       .onStart(()=>{
          // initial value assignment of shared values
        })
       .onUpdate((event)=>{
          dragY.value = event.absoluteY
        })
       .onEnd(()=>{
          // resetting shared values
       })

When scrolling starts, after sometime, onEnd never gets called. It seems like scrolling steals the PanGesture. None of the onTouchesCancelled or onFinalize also gets called.

Please help here. Versions used:-

  • "react-native-reanimated": "3.8.0"
  • "react-native-gesture-handler": "2.17.1"

I am doing all this on iOS

发布评论

评论列表(0)

  1. 暂无评论