software-mansion / react-native-gesture-handler

Declarative API exposing platform native touch and gesture system to React Native.
https://docs.swmansion.com/react-native-gesture-handler/
MIT License
6.13k stars 982 forks source link

GestureDetector with Gesture.Pan() breaks FlatList in android only #3140

Closed freeboub closed 1 month ago

freeboub commented 1 month ago

Description

If we include a FlatList inside a GestureDetector configured with Pan, The flatlist cannot be scrolled.

Additional comment:

Background. In our app with have a flatlist inside a modal. we should be able to swipe down the modal to close it (it is the Pan Gesture detector usage). It works on ios, not on android.

Additional test done: I also try to add a Gesture.Native(); as explained here: https://stackoverflow.com/questions/76835869/flat-list-inside-a-gesture-detector But it doesn't help

Steps to reproduce

Here is the smallest code possible to reproduce the issue:

const data = new Array(50).fill(0).map((_, index) => ({ id: index }))

export const AnimatedFlatList = () => {
  return (
      <FlatList
        data={data}
        renderItem={() => {
          return <View style={{
                        height: 80,
                        width: 80,
                        backgroundColor: '#78CAD2',
                        alignSelf: 'center',
                        margin: 20,
                }}
            />
        }}
      />
  )
}

const App = () => {
  const panGesture = Gesture.Pan()
  // const nativeGesture = Gesture.Native();
  // const gesture = Gesture.Simultaneous(panGesture, nativeGesture);
  return (
    <GestureHandlerRootView style={{ flex: 1 }}>
      <GestureDetector gesture={panGesture}>
        <AnimatedFlatList/>
      </GestureDetector>
    </GestureHandlerRootView>
  )
}

Snack or a link to a repository

https://github.com/freeboub/bug-react-native-gestureHandler-FlatList

Gesture Handler version

2.20.0

React Native version

0.74.5 in the sample - 0.75.3 in our production app

Platforms

Android

JavaScript runtime

Hermes

Workflow

React Native (without Expo)

Architecture

Paper (Old Architecture)

Build type

Debug mode

Device

Android emulator

Device model

No response

Acknowledgements

Yes

freeboub commented 1 month ago

I triple check think the answer is here: https://github.com/software-mansion/react-native-gesture-handler/issues/1103#issuecomment-2188098178 It would make sense to put this information on documentation I think ...

freeboub commented 1 month ago

The linked fix works on my sample app, I will investigate more and update here ...

j-piasecki commented 1 month ago

Yeah, the solution is to use Gesture.Native and make it simultaneous with Pan gesture. You can also check this gist which may be helpful for your use-case.

freeboub commented 1 month ago

Thank you @j-piasecki, OK for me, let's close the issue

FabioRocha462 commented 1 month ago

Good afternoon, I'm going through the same problem, I did what they told me to do, but it doesn't work.

freeboub commented 1 month ago

Good afternoon, I'm going through the same problem, I did what they told me to do, but it doesn't work.

I had multiple native gesture to handle. I tried to remove them 1 by 1 to identify this.

Additionally I saw some weird behavior inside the modal, I found a workaround. If I find time, I will try to replicate it in a sample.

freeboub commented 1 month ago

Just try with this version, It works fine

const App = () => {
  const nativeSectionScrollPan = Gesture.Native();
  const nativeSectionScrollPan2 = Gesture.Native();

  const panGesture = Gesture.Pan()
                        .simultaneousWithExternalGesture(nativeSectionScrollPan)
                        .onBegin(()=> {console.log('onBegin')})

  const [isOpen, setIsOpen] = useState(false)
  const onPress = () => {
    setIsOpen((open)=> !open)
  }

  return (
    <GestureHandlerRootView style={{ flex: 1 }}>
       <Pressable style={{width: 100, height: 100, backgroundColor: 'purple'}} onPress={onPress}/>
       <Modal visible={isOpen}>
        <GestureHandlerRootView style={{ flex: 1 }}>
          <GestureDetector gesture={panGesture}>
            <View style={{height: '100%', width: '100%'}}>
              <GestureDetector gesture={nativeSectionScrollPan2}>
                <Pressable style={{width: 100, height: 100, backgroundColor: 'pink'}} onPress={onPress}/>
              </GestureDetector>
              <GestureDetector gesture={nativeSectionScrollPan}>
                <AnimatedFlatList/>
              </GestureDetector>
            </View>
          </GestureDetector>
        </GestureHandlerRootView>
       </Modal>
     </GestureHandlerRootView>
  )
}
badalsaibo commented 1 month ago

When Flatlist's item is wrapped with GestureDetector gesture={swipeGesture} the scroll of Flatlist doesn't work? Is there anything we have to add on the Flatlist? I tried using the rngh's Flatlist component but it still doesn't work.

EDIT: Adding the below value worked

    .failOffsetY([-5, 5])
    .activeOffsetX([-5, 5]);