Update touch/measure/hotspot to all use same coordinate space

Reviewed By: astreet

Differential Revision: D2731165

fb-gh-sync-id: 729943233af66f139907cac2002fed4038b3fa6a
This commit is contained in:
Dave Miller 2015-12-10 02:57:33 -08:00 committed by facebook-github-bot-5
parent 423202072c
commit 5775d9e1d0
3 changed files with 35 additions and 20 deletions

View File

@ -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();
}

View File

@ -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);
}

View File

@ -47,7 +47,6 @@ public class ReactViewManager extends ViewGroupManager<ReactViewGroup> {
};
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<ReactViewGroup> {
"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;