diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSTouchDispatcher.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSTouchDispatcher.java index 97d366a53..ba8d56be8 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSTouchDispatcher.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSTouchDispatcher.java @@ -30,6 +30,7 @@ public class JSTouchDispatcher { private int mTargetTag = -1; private final float[] mTargetCoordinates = new float[2]; private boolean mChildIsHandlingNativeGesture = false; + private long mGestureStartTime = TouchEvent.UNSET; private final ViewGroup mRootViewGroup; private final TouchEventCoalescingKeyHelper mTouchEventCoalescingKeyHelper = new TouchEventCoalescingKeyHelper(); @@ -72,6 +73,7 @@ public class JSTouchDispatcher { // {@link #findTargetTagForTouch} to find react view ID that will be responsible for handling // this gesture mChildIsHandlingNativeGesture = false; + mGestureStartTime = ev.getEventTime(); mTargetTag = TouchTargetHelper.findTargetTagAndCoordinatesForTouch( ev.getX(), ev.getY(), @@ -83,6 +85,7 @@ public class JSTouchDispatcher { mTargetTag, TouchEventType.START, ev, + mGestureStartTime, mTargetCoordinates[0], mTargetCoordinates[1], mTouchEventCoalescingKeyHelper)); @@ -105,10 +108,12 @@ public class JSTouchDispatcher { mTargetTag, TouchEventType.END, ev, + mGestureStartTime, mTargetCoordinates[0], mTargetCoordinates[1], mTouchEventCoalescingKeyHelper)); mTargetTag = -1; + mGestureStartTime = TouchEvent.UNSET; } else if (action == MotionEvent.ACTION_MOVE) { // Update pointer position for current gesture eventDispatcher.dispatchEvent( @@ -116,6 +121,7 @@ public class JSTouchDispatcher { mTargetTag, TouchEventType.MOVE, ev, + mGestureStartTime, mTargetCoordinates[0], mTargetCoordinates[1], mTouchEventCoalescingKeyHelper)); @@ -126,6 +132,7 @@ public class JSTouchDispatcher { mTargetTag, TouchEventType.START, ev, + mGestureStartTime, mTargetCoordinates[0], mTargetCoordinates[1], mTouchEventCoalescingKeyHelper)); @@ -136,6 +143,7 @@ public class JSTouchDispatcher { mTargetTag, TouchEventType.END, ev, + mGestureStartTime, mTargetCoordinates[0], mTargetCoordinates[1], mTouchEventCoalescingKeyHelper)); @@ -149,6 +157,7 @@ public class JSTouchDispatcher { ); } mTargetTag = -1; + mGestureStartTime = TouchEvent.UNSET; } else { FLog.w( ReactConstants.TAG, @@ -176,6 +185,7 @@ public class JSTouchDispatcher { mTargetTag, TouchEventType.CANCEL, androidEvent, + mGestureStartTime, mTargetCoordinates[0], mTargetCoordinates[1], mTouchEventCoalescingKeyHelper)); diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/TouchEvent.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/TouchEvent.java index 0262f0bd0..03d922852 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/TouchEvent.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/TouchEvent.java @@ -15,6 +15,7 @@ import android.support.v4.util.Pools; import android.view.MotionEvent; import com.facebook.infer.annotation.Assertions; +import com.facebook.react.bridge.SoftAssertions; /** * An event representing the start, end or movement of a touch. Corresponds to a single @@ -31,10 +32,13 @@ public class TouchEvent extends Event { private static final Pools.SynchronizedPool EVENTS_POOL = new Pools.SynchronizedPool<>(TOUCH_EVENTS_POOL_SIZE); + public static final long UNSET = Long.MIN_VALUE; + public static TouchEvent obtain( int viewTag, TouchEventType touchEventType, MotionEvent motionEventToCopy, + long gestureStartTime, float viewX, float viewY, TouchEventCoalescingKeyHelper touchEventCoalescingKeyHelper) { @@ -46,6 +50,7 @@ public class TouchEvent extends Event { viewTag, touchEventType, motionEventToCopy, + gestureStartTime, viewX, viewY, touchEventCoalescingKeyHelper); @@ -67,30 +72,33 @@ public class TouchEvent extends Event { int viewTag, TouchEventType touchEventType, MotionEvent motionEventToCopy, + long gestureStartTime, float viewX, float viewY, TouchEventCoalescingKeyHelper touchEventCoalescingKeyHelper) { super.init(viewTag); + SoftAssertions.assertCondition(gestureStartTime != UNSET, + "Gesture start time must be initialized"); short coalescingKey = 0; int action = (motionEventToCopy.getAction() & MotionEvent.ACTION_MASK); switch (action) { case MotionEvent.ACTION_DOWN: - touchEventCoalescingKeyHelper.addCoalescingKey(motionEventToCopy.getDownTime()); + touchEventCoalescingKeyHelper.addCoalescingKey(gestureStartTime); break; case MotionEvent.ACTION_UP: - touchEventCoalescingKeyHelper.removeCoalescingKey(motionEventToCopy.getDownTime()); + touchEventCoalescingKeyHelper.removeCoalescingKey(gestureStartTime); break; case MotionEvent.ACTION_POINTER_DOWN: case MotionEvent.ACTION_POINTER_UP: - touchEventCoalescingKeyHelper.incrementCoalescingKey(motionEventToCopy.getDownTime()); + touchEventCoalescingKeyHelper.incrementCoalescingKey(gestureStartTime); break; case MotionEvent.ACTION_MOVE: coalescingKey = - touchEventCoalescingKeyHelper.getCoalescingKey(motionEventToCopy.getDownTime()); + touchEventCoalescingKeyHelper.getCoalescingKey(gestureStartTime); break; case MotionEvent.ACTION_CANCEL: - touchEventCoalescingKeyHelper.removeCoalescingKey(motionEventToCopy.getDownTime()); + touchEventCoalescingKeyHelper.removeCoalescingKey(gestureStartTime); break; default: throw new RuntimeException("Unhandled MotionEvent action: " + action);