gorhom / react-native-bottom-sheet

A performant interactive bottom sheet with fully configurable options ๐Ÿš€
https://gorhom.dev/react-native-bottom-sheet/
MIT License
7.04k stars 770 forks source link

[v4] pinch and zoom of map within bottom-sheet on Android #629

Closed mlecoq closed 3 years ago

mlecoq commented 3 years ago

Bug

I have added a map (from react-native-mapbox) in a bottom sheet. On Android, pinch and zoom are in conflict with bottom sheet behavior (on iOS everything works fine). I have tried to wrap MapView with a NativeViewGestureHandler as suggested in the documentation

const MapView = createNativeWrapper(MapboxGL.MapView, {
  disallowInterruption: true,
});

I can move within my map, pinch tends to move bottom sheet and zoom has no visual effect.

Here is my bottom sheet

  <BottomSheetModal
        name="layers"
        ref={positionBottomSheet}
        snapPoints={snapPoints}
        backdropComponent={CustomBackdrop}
        handleComponent={HandleComponent}>
        {state.location && (
          <Box flex={1} paddingTop={3}>
            <MapboxGL.MapView compassViewPosition={3} logoEnabled={false} style={styles.mapView}>
              <MapboxGL.Camera
                ref={camera}
                zoomLevel={19}
                centerCoordinate={[state.location.lng, state.location.lat]}
              />
              <MapboxGL.ShapeSource
                id="treatedPinsSource"
                shape={{
                  type: 'Point',
                  coordinates: [state.location.lng, state.location.lat],
                }}>
                <MapboxGL.SymbolLayer id="treatedMapPinsLayer" style={{iconImage: untreated}} />
              </MapboxGL.ShapeSource>
            </MapboxGL.MapView>
          </Box>
        )}
      </BottomSheetModal>

Box is from native-base

Environment info

Library Version
@gorhom/bottom-sheet 4.0.3
react-native 0.63.4 (expo sdk 42)
react-native-reanimated 2.2.0
react-native-gesture-handler 1.10.3

Steps To Reproduce

  1. Create a new expo app with react-native-bottom-sheet and react-native-maps
  2. Add map in bottom-sheet
  3. Try to pinch and zoom in map on android

Describe what you expected to happen:

  1. I can pinch and zoom in the map which is in bottom-sheet

Reproducible sample code

I have made a small example here: https://github.com/mlecoq/bottomsheet-map

To get a token from mapbox, you need to have an account : https://account.mapbox.com/auth/signup/

And then replace MAPBOX_ACCESS_TOKEN in the code

gorhom commented 3 years ago

you can achieve your goal with passing the NativeViewGestureHandler ref to BottomSheet or BottomSheetModal waitFor prop, like:

      <BottomSheet
        {...}
        waitFor={nativeGestureRef}
      >
        <BottomSheetView style={styles.container}>
          <NativeViewGestureHandler
            ref={nativeGestureRef}
            disallowInterruption={true}
          >
            <MapView {...} />
          </NativeViewGestureHandler>
        </BottomSheetView>
      </BottomSheet>
gorhom commented 3 years ago

@mlecoq let me know if the post above solves your issue ๐Ÿ‘

mlecoq commented 3 years ago

I will check, thanks !

mlecoq commented 3 years ago

@gorhom yes it works well, thanks a lot !

MateuszRostkowski commented 1 year ago

In case someone will be using this with expo 48 and react-native-gesture-handler 2.9.0, you can do it like this:

const BottomSheetMap = () => {
  const panGestureRef = useRef(Gesture.Pan())
  const pinchGesture = Gesture.Pinch().withRef(panGestureRef)

  return (
      <BottomSheet
        {...}
        waitFor={panGestureRef}
      >
        <BottomSheetView style={styles.container}>
          <GestureDetector 
             gesture={pinchGesture}
             // @ts-expect-error: this prop is not added in types but it's working
             disallowInterruption={true}
          >
            <MapView {...} />
          </GestureDetector>
        </BottomSheetView>
      </BottomSheet>
  )
}

Adding the disallowInterruption={true} prop to Gesture Detector solves all issues, but looks like the library is not expecting to receiving this prop, it's possible that in next releases this will need another update ๐Ÿ™ˆ

ngdbao commented 4 months ago

In case someone will be using this with expo 48 and react-native-gesture-handler 2.9.0, you can do it like this:

const BottomSheetMap = () => {
  const panGestureRef = useRef(Gesture.Pan())
  const pinchGesture = Gesture.Pinch().withRef(panGestureRef)

  return (
      <BottomSheet
        {...}
        waitFor={panGestureRef}
      >
        <BottomSheetView style={styles.container}>
          <GestureDetector 
             gesture={pinchGesture}
             // @ts-expect-error: this prop is not added in types but it's working
             disallowInterruption={true}
          >
            <MapView {...} />
          </GestureDetector>
        </BottomSheetView>
      </BottomSheet>
  )
}

Adding the disallowInterruption={true} prop to Gesture Detector solves all issues, but looks like the library is not expecting to receiving this prop, it's possible that in next releases this will need another update ๐Ÿ™ˆ

OMG, this charm should go straight to the readme docs