React-native-gesture-handler: Receiving simultaneous ScrollView and GestureHandler events

Created on 4 Mar 2019  路  5Comments  路  Source: software-mansion/react-native-gesture-handler

Is it possible to receive events for a handler, e.g. PanGestureHandler, and a ScrollView at the same time? I鈥檓 finding that a ScrollView fully consumes a touch event, even with simultaneousHandlers set, so that a gesture handler that contains the ScrollView never receives the touch as long as the ScrollView is enabled.

Most helpful comment

There is no documentation about NativeViewGestureHandler on official site, but the only mention of it says that you can use FlatList from react-native-gesture-handler with simultaneousHandlers instead of wrapping it inside NativeViewGestureHandler.

But you cannot

import { FlatList, PanGestureHandler } from 'react-native-gesture-handler';

// This handler will only fire if FlatList does not detect scroll
<PanGestureHandler
  ref={panRef}
  simultaneousHandlers={listRef}
>
  <FlatList
    ref={listRef}
    simultaneousHandlers={panRef}
    ...
  />
</PanGestureHandler>

So you still should use FlatListONLY from react-native and wrap it in NativeViewGestureHandler:

import { FlatList } from 'react-native';
import { PanGestureHandler, NativeViewGestureHandler } from 'react-native-gesture-handler';

<PanGestureHandler
  ref={panRef}
  simultaneousHandlers={listRef}
>
  <NativeViewGestureHandler
    ref={listRef}
    simultaneousHandlers={panRef}
  />
    <FlatList/>
  </NativeViewGestureHandler>
</PanGestureHandler>

There is no FlatList in current documentation from this repo. But it was added in this PR. IDK

All 5 comments

Answer: Wrapping the ScrollView in a NativeViewGestureHandler, with both gesture handlers pointing to each other's refs in the simultaneousHandlers prop, works perfectly.

There is no documentation about NativeViewGestureHandler on official site, but the only mention of it says that you can use FlatList from react-native-gesture-handler with simultaneousHandlers instead of wrapping it inside NativeViewGestureHandler.

But you cannot

import { FlatList, PanGestureHandler } from 'react-native-gesture-handler';

// This handler will only fire if FlatList does not detect scroll
<PanGestureHandler
  ref={panRef}
  simultaneousHandlers={listRef}
>
  <FlatList
    ref={listRef}
    simultaneousHandlers={panRef}
    ...
  />
</PanGestureHandler>

So you still should use FlatListONLY from react-native and wrap it in NativeViewGestureHandler:

import { FlatList } from 'react-native';
import { PanGestureHandler, NativeViewGestureHandler } from 'react-native-gesture-handler';

<PanGestureHandler
  ref={panRef}
  simultaneousHandlers={listRef}
>
  <NativeViewGestureHandler
    ref={listRef}
    simultaneousHandlers={panRef}
  />
    <FlatList/>
  </NativeViewGestureHandler>
</PanGestureHandler>

There is no FlatList in current documentation from this repo. But it was added in this PR. IDK

@damikdk thanks, your research helped me.

I'd add one caveat though. For anybody planning to use an Animated.event for a PanGestureHandler onHandlerStateChange for example. In that case one must wrap a NativeViewGestureHandler inside an Animated.View. Otherwise the app will be failing with an error Nesting touch handlers with native animated driver is not supported yet.

Credits:聽#71

Just in case, here's a full example:
`js const ScrollContainer = styled(Animated.ScrollView).attrs({ scrollEventThrottle: 16, contentContainerStyle: { paddingBottom: 40 }, })

const Container = React.forwardRef((props, ref) => {
const handlerRef = useRef()
const { onScroll, onHandlerStateChange, children } = props

return

<Animated.View>

  <NativeViewGestureHandler ref={handlerRef}>
    <ScrollContainer ref={ref} {...{onScroll}}>
      {children}
    </ScrollContainer>
  </NativeViewGestureHandler>

</Animated.View>


})

I use [email protected]. It seems neither of the suggested solutions work. I've tried all kinds of simultaneousHandlers combinations, ScrollViews from react-native-gesture-handler and from react-native etc.

Here:

class List extends PureComponent<Props> {
  panRef
  listRef
  render () {
    const { children } = this.props
    return (
      <View style={styles.container}>
        <PanGestureHandler
          onGestureEvent={() => console.log('onGestureEvent')}
          ref={ref => (this.panRef = ref)}
          simultaneousHandlers={this.listRef}
        >
          <NativeViewGestureHandler
            ref={ref => (this.listRef = ref)}
            simultaneousHandlers={this.panRef}
          >
            <ScrollView
              // scrollEnabled={false}
              style={styles.foodListScroll}
            >
              {children}
            </ScrollView>
          </NativeViewGestureHandler>
        </PanGestureHandler>
      </View>
    )
  }
}

PanGestureHandler fires onGestureEvent only when the ScrollView is disabled with scrollEnabled={false}.

@damikdk @yzalvov could you take a look?

Was this page helpful?
0 / 5 - 0 ratings