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.03k stars 970 forks source link

PinchGestureHandler and PanGestureHandler not working simultaneously #927

Open IsaacGluck opened 4 years ago

IsaacGluck commented 4 years ago

Thanks in advance for the help! Please let me know if I can provide any extra information!

Refs:

  this.panHandler = React.createRef();
  this.pinchHandler = React.createRef();

Handlers:

  const scale = new Animated.Value(1);
  const onZoomEvent = (zoomeEvent) => {
    if (zoomeEvent.nativeEvent.scale >= 1) {
      return Animated.event([{
        nativeEvent: {
          scale,
        },
      }])(zoomeEvent);
    } else {
      return Animated.event([{ nativeEvent: { scale: 1 } }])(zoomeEvent);
    }
  };
  const onZoomStateChange = (event) => {
    if (event.nativeEvent.oldState === State.ACTIVE) {
      Animated.spring(scale, {
        toValue: 1,
      }).start();
    }
  };

  const translateX = new Animated.Value(0);
  const translateY = new Animated.Value(0);
  const handlePanEvent = (panEvent) => {
    return Animated.event(
      [{ nativeEvent: { translationX: translateX, translationY: translateY } }],
    )(panEvent);
  };
  const onPanStateChange = (event) => {
    if (event.nativeEvent.oldState === State.ACTIVE) {
      Animated.spring(translateX, {
        toValue: 0,
      }).start();
      Animated.spring(translateY, {
        toValue: 0,
      }).start();
    }
  };

JSX:

  <PinchGestureHandler
    ref={this.pinchHandler}
    simultaneousHandlers={this.panHandler}
    onGestureEvent={onZoomEvent}
    onHandlerStateChange={onZoomStateChange}
  >
    <Animated.View>
      <PanGestureHandler
        ref={this.panHandler}
        simultaneousHandlers={this.pinchHandler}
        minPointers={2}
        onGestureEvent={handlePanEvent}
        onHandlerStateChange={onPanStateChange}
      >
        <Animated.View>
          <Animated.Image
            source={{ uri: meme.get('url') }}
            style={{
              width: displayWidth,
              height: displayHeight,
              transform: [{ scale }, { translateX }, { translateY }],
            }}
            resizeMode="contain"
          />
        </Animated.View>
      </PanGestureHandler>
    </Animated.View>
  </PinchGestureHandler>
abandohess commented 4 years ago

+1 having same issue

Enoinoo commented 4 years ago

Having the same issue trying to use PanGestureHandler for dragging movement and PinchGestureHandler for zooming.

Is there a fix for this yet?

Enoinoo commented 4 years ago

I think this works fine on Android, but not on iOS.

german970814 commented 4 years ago

The issue is present on iOS version 13.3. Lower versions don't have this issue. Any workaround about it?

Using: Platform: iOS 13.3 Expo SDK: 35.0.0 react-native-gesture-handler: 1.3.0

zulkarnainshariff commented 4 years ago

I had a problem with this too, solved it by putting a flex: 1 to all the

Enoinoo commented 4 years ago

I had a problem with this too, solved it by putting a flex: 1 to all the

I just tried this but the view just disappears.

viveKing21 commented 4 years ago

I think this works fine on Android, but not on iOS.

nah its not working on android,

import React from 'react' import {View,Image,Animated, Button} from 'react-native' import {PinchGestureHandler} from 'react-native-gesture-handler' export default function pinchZoom(){ const scale=React.useRef(new Animated.Value(1)).current; const HandlePinch=new Animated.event( [{nativeEvent:{scale:scale}}] , { useNativeDriver: false }) const anime=new Animated.ValueXY(0,0) return(

)

}

its not even moving, dont know what im doing wrong help plz,

majonathany commented 4 years ago

Any fix yet?

jakub-gonet commented 4 years ago

Could you provide a minimal, working example in form of snack, repo, or code block here?

wadewadewadewadewadewade commented 3 years ago

I don't know if it helps, but I'm having a similar issue, and I've made a snack that can reproduce it...sort of...

https://snack.expo.io/@aproximation/react-native-draggable

My actual Android 9 device is behaving the way iPhone 8 in emulation is behaving on that snack: the first drag is jerky but sort of works, and subsequent drags have no animation, and the object just appears at the new destination when you release the mouse.

I tried to update the README for that snack to describe what I'm seeing

RahulRijhwani commented 3 years ago

I am stuck at same issue Any update

vivrkerror404 commented 3 years ago

I am using PanResponder and pinch GestureHandler and faced the same issue and I fixed it by including a condition(gestureState.numberActiveTouches) in onStartShouldSetPanResponder value inside PanResponder.create(), below is my code eg:- gestureState.numberActiveTouches = 1 means touch event gestureState.numberActiveTouches = 2 means pinch event

  onStartShouldSetPanResponder: (evt, gestureState) => {if(gestureState.numberActiveTouches == 2){return false } else{return true} },
seancheung commented 3 years ago

Same here. It works on Android but not iOS. What about pinch and pan both with tow touched?(like the iOS photo markup app)

DanleyCr7 commented 3 years ago

react-native link react-native-gesture-handler

path android\app\src\main\java\com\hans_patient\MainActivity.java;

import com.facebook.react.ReactActivityDelegate; import com.facebook.react.ReactRootView; import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;

@Override protected ReactActivityDelegate createReactActivityDelegate() { return new ReactActivityDelegate(this, getMainComponentName()) { @Override protected ReactRootView createRootView() { return new RNGestureHandlerEnabledRootView(MainActivity.this); } }; }

amanda-t commented 3 years ago

I had the same issue where my simultaneous pinch/2-finger pan on an image worked on Android but not iOS, but then I found out it just doesn't work on my older first-generation iPhone SE. It does work on an iPhone XR. So maybe it's an older device thing?

Made a simple Snack here: https://snack.expo.io/@amandatusing/simultaneous-pinch-and-zoom-gestures.

It's working on a Google Pixel 4a Android version 11 and an iPhone XR iOS 14.6. On iPhone SE iOS 14.6 the gestures can't happen simultaneously. You can either 2-finger pan or pinch separately, but not together.

And it's not just my example. The react-native-gesture-handler demos, like scale and rotate, also don't work on my 1st-gen iPhone SE simultaneously.

UPDATE: Although simultaneous pinch and pan wasn't working on my phone when developing locally with Expo, it does work in the built App in Testflight.

innocentmasuki commented 1 year ago

I am using PanResponder and pinch GestureHandler and faced the same issue and I fixed it by including a condition(gestureState.numberActiveTouches) in onStartShouldSetPanResponder value inside PanResponder.create(), below is my code eg:- gestureState.numberActiveTouches = 1 means touch event gestureState.numberActiveTouches = 2 means pinch event

  onStartShouldSetPanResponder: (evt, gestureState) => {if(gestureState.numberActiveTouches == 2){return false } else{return true} },

This fixed the problem for me

niujianqiang123 commented 9 months ago

react-native-gesture-handler v2.13.4 iOS v17.0 已修复,当我用option+mouse进行缩放,因为两个触点的中心,并没有发生移动,所以drag不会触发,当我用alt+mouse放置一个偏移的点,进行两个点缩放时,拖拽是生效的

niujianqiang123 commented 9 months ago

code is this

// -------------------svg拖拽相关逻辑-----------------------
  const dragGesture = Gesture.Pan()
    .onStart(_e => {})
    .onUpdate(e => {
      const x = start.value.x + e.translationX;
      const y = start.value.y + e.translationY;
      offset.value = {
        x,
        y,
      };
    })
    .onEnd(() => {
      start.value = {
        x: offset.value.x,
        y: offset.value.y,
      };
    });
  // --------------svg缩放相关逻辑----------------
  const zoomGesture = Gesture.Pinch()
    .onStart(_e => {})
    .onUpdate(e => {
      const scaleValue = savedScale.value * e.scale;
      if (scaleValue > 3 || scaleValue < 1) {
        return;
      }
      scale.value = scaleValue;
    })
    .onEnd(_e => {
      savedScale.value = scale.value;
    })
    .simultaneousWithExternalGesture(dragGesture);
  const composed = Gesture.Simultaneous(dragGesture, zoomGesture);

  return (
        <GestureDetector gesture={composed}>
          <Svg />
        </GestureDetector>
BrandonCao commented 7 months ago

Any update on this?