From 5775d9e1d00b4c919ee97bdf780c42bab7cb2d5e Mon Sep 17 00:00:00 2001 From: Dave Miller Date: Thu, 10 Dec 2015 02:57:33 -0800 Subject: [PATCH] Update touch/measure/hotspot to all use same coordinate space Reviewed By: astreet Differential Revision: D2731165 fb-gh-sync-id: 729943233af66f139907cac2002fed4038b3fa6a --- .../uimanager/NativeViewHierarchyManager.java | 11 +++++- .../react/uimanager/events/TouchesHelper.java | 38 ++++++++++++------- .../react/views/view/ReactViewManager.java | 6 +-- 3 files changed, 35 insertions(+), 20 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java index ad1950043..dd40b7a16 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java @@ -466,8 +466,15 @@ public class NativeViewHierarchyManager { throw new NoSuchNativeViewException("No native view for " + tag + " currently exists"); } - // Puts x/y in outputBuffer[0]/[1] - v.getLocationOnScreen(outputBuffer); + View rootView = (View) RootViewUtil.getRootView(v); + rootView.getLocationInWindow(outputBuffer); + int rootX = outputBuffer[0]; + int rootY = outputBuffer[1]; + + v.getLocationInWindow(outputBuffer); + + outputBuffer[0] = outputBuffer[0] - rootX; + outputBuffer[1] = outputBuffer[1] - rootY; outputBuffer[2] = v.getWidth(); outputBuffer[3] = v.getHeight(); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/TouchesHelper.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/TouchesHelper.java index e431fa7ae..d312a4020 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/TouchesHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/TouchesHelper.java @@ -35,25 +35,35 @@ import com.facebook.react.uimanager.PixelUtil; * given {@param event} instance. This method use {@param reactTarget} parameter to set as a * target view id associated with current gesture. */ - private static WritableArray createsPointersArray(int reactTarget, TouchEvent touchEvent) { - MotionEvent event = touchEvent.getMotionEvent(); - + private static WritableArray createsPointersArray(int reactTarget, TouchEvent event) { WritableArray touches = Arguments.createArray(); + MotionEvent motionEvent = event.getMotionEvent(); - // Calculate raw-to-relative offset as getRawX() and getRawY() can only return values for the - // pointer at index 0. We use those value to calculate "raw" coordinates for other pointers - float offsetX = event.getRawX() - event.getX(); - float offsetY = event.getRawY() - event.getY(); + // Calculate the coordinates for the target view. + // The MotionEvent contains the X,Y of the touch in the coordinate space of the root view + // The TouchEvent contains the X,Y of the touch in the coordinate space of the target view + // Subtracting them allows us to get the coordinates of the target view's top left corner + // We then use this when computing the view specific touches below + // Since only one view is actually handling even multiple touches, the values are all relative + // to this one target view. + float targetViewCoordinateX = motionEvent.getX() - event.getViewX(); + float targetViewCoordinateY = motionEvent.getY() - event.getViewY(); - for (int index = 0; index < event.getPointerCount(); index++) { + for (int index = 0; index < motionEvent.getPointerCount(); index++) { WritableMap touch = Arguments.createMap(); - touch.putDouble(PAGE_X_KEY, PixelUtil.toDIPFromPixel(event.getX(index) + offsetX)); - touch.putDouble(PAGE_Y_KEY, PixelUtil.toDIPFromPixel(event.getY(index) + offsetY)); - touch.putDouble(LOCATION_X_KEY, PixelUtil.toDIPFromPixel(event.getX(index))); - touch.putDouble(LOCATION_Y_KEY, PixelUtil.toDIPFromPixel(event.getY(index))); + // pageX,Y values are relative to the RootReactView + // the motionEvent already contains coordinates in that view + touch.putDouble(PAGE_X_KEY, PixelUtil.toDIPFromPixel(motionEvent.getX(index))); + touch.putDouble(PAGE_Y_KEY, PixelUtil.toDIPFromPixel(motionEvent.getY(index))); + // locationX,Y values are relative to the target view + // To compute the values for the view, we subtract that views location from the event X,Y + float locationX = motionEvent.getX(index) - targetViewCoordinateX; + float locationY = motionEvent.getY(index) - targetViewCoordinateY; + touch.putDouble(LOCATION_X_KEY, PixelUtil.toDIPFromPixel(locationX)); + touch.putDouble(LOCATION_Y_KEY, PixelUtil.toDIPFromPixel(locationY)); touch.putInt(TARGET_KEY, reactTarget); - touch.putDouble(TIMESTAMP_KEY, event.getEventTime()); - touch.putDouble(POINTER_IDENTIFIER_KEY, event.getPointerId(index)); + touch.putDouble(TIMESTAMP_KEY, motionEvent.getEventTime()); + touch.putDouble(POINTER_IDENTIFIER_KEY, motionEvent.getPointerId(index)); touches.pushMap(touch); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java index 6e002fb9f..9b74294ad 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java @@ -47,7 +47,6 @@ public class ReactViewManager extends ViewGroupManager { }; private static final int CMD_HOTSPOT_UPDATE = 1; private static final int CMD_SET_PRESSED = 2; - private static final int[] sLocationBuf = new int[2]; @ReactProp(name = "accessible") public void setAccessible(ReactViewGroup view, boolean accessible) { @@ -160,9 +159,8 @@ public class ReactViewManager extends ViewGroupManager { "Illegal number of arguments for 'updateHotspot' command"); } if (Build.VERSION.SDK_INT >= 21) { - root.getLocationOnScreen(sLocationBuf); - float x = PixelUtil.toPixelFromDIP(args.getDouble(0)) - sLocationBuf[0]; - float y = PixelUtil.toPixelFromDIP(args.getDouble(1)) - sLocationBuf[1]; + float x = PixelUtil.toPixelFromDIP(args.getDouble(0)); + float y = PixelUtil.toPixelFromDIP(args.getDouble(1)); root.drawableHotspotChanged(x, y); } break;