Skip to content

Commit

Permalink
Add measureInWindow on Android
Browse files Browse the repository at this point in the history
Summary:public
This adds the capability to get a View in absolute position on the screen, not just relative to the RootView.  This is the Android implementation

Reviewed By: andreicoman11

Differential Revision: D2939170

fb-gh-sync-id: 658f1ebe6a458088f657a7469389add1a12222cd
shipit-source-id: 658f1ebe6a458088f657a7469389add1a12222cd
  • Loading branch information
Dave Miller authored and facebook-github-bot-4 committed Feb 17, 2016
1 parent f9e81d9 commit b26f699
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,28 @@ public void measure(int tag, int[] outputBuffer) {
outputBuffer[3] = v.getHeight();
}

/**
* Returns the coordinates of a view relative to the entire phone screen (not just the RootView
* which is what measure will return)
*
* @param tag - the tag for the view
* @param outputBuffer - output buffer that contains [x,y,width,height] of the view in coordinates
* relative to the device window
*/
public void measureInWindow(int tag, int[] outputBuffer) {
UiThreadUtil.assertOnUiThread();
View v = mTagsToViews.get(tag);
if (v == null) {
throw new NoSuchNativeViewException("No native view for " + tag + " currently exists");
}

v.getLocationOnScreen(outputBuffer);

// outputBuffer[0,1] already contain what we want
outputBuffer[2] = v.getWidth();
outputBuffer[3] = v.getHeight();
}

public int findTargetTagForTouch(int reactTag, float touchX, float touchY) {
View view = mTagsToViews.get(reactTag);
if (view == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -380,8 +380,8 @@ public void findSubviewIn(int reactTag, float targetX, float targetY, Callback c
}

/**
* Determines the location on screen, width, and height of the given view and returns the values
* via an async callback.
* Determines the location on screen, width, and height of the given view relative to the root
* view and returns the values via an async callback.
*/
public void measure(int reactTag, Callback callback) {
// This method is called by the implementation of JS touchable interface (see Touchable.js for
Expand All @@ -391,6 +391,15 @@ public void measure(int reactTag, Callback callback) {
mOperationsQueue.enqueueMeasure(reactTag, callback);
}

/**
* Determines the location on screen, width, and height of the given view relative to the device
* screen and returns the values via an async callback. This is the absolute position including
* things like the status bar
*/
public void measureInWindow(int reactTag, Callback callback) {
mOperationsQueue.enqueueMeasureInWindow(reactTag, callback);
}

/**
* Measures the view specified by tag relative to the given ancestorTag. This means that the
* returned x, y are relative to the origin x, y of the ancestor view. Results are stored in the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,16 @@ public void measure(int reactTag, Callback callback) {
mUIImplementation.measure(reactTag, callback);
}

/**
* Determines the location on screen, width, and height of the given view relative to the device
* screen and returns the values via an async callback. This is the absolute position including
* things like the status bar
*/
@ReactMethod
public void measureInWindow(int reactTag, Callback callback) {
mUIImplementation.measureInWindow(reactTag, callback);
}

/**
* Measures the view specified by tag relative to the given ancestorTag. This means that the
* returned x, y are relative to the origin x, y of the ancestor view. Results are stored in the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,38 @@ public void execute() {
}
}

private final class MeasureInWindowOperation implements UIOperation {

private final int mReactTag;
private final Callback mCallback;

private MeasureInWindowOperation(
final int reactTag,
final Callback callback) {
super();
mReactTag = reactTag;
mCallback = callback;
}

@Override
public void execute() {
try {
mNativeViewHierarchyManager.measureInWindow(mReactTag, mMeasureBuffer);
} catch (NoSuchNativeViewException e) {
// Invoke with no args to signal failure and to allow JS to clean up the callback
// handle.
mCallback.invoke();
return;
}

float x = PixelUtil.toDIPFromPixel(mMeasureBuffer[0]);
float y = PixelUtil.toDIPFromPixel(mMeasureBuffer[1]);
float width = PixelUtil.toDIPFromPixel(mMeasureBuffer[2]);
float height = PixelUtil.toDIPFromPixel(mMeasureBuffer[3]);
mCallback.invoke(x, y, width, height);
}
}

private ArrayList<UIOperation> mOperations = new ArrayList<>();

private final class FindTargetForTouchOperation implements UIOperation {
Expand Down Expand Up @@ -634,6 +666,14 @@ public void enqueueMeasure(
new MeasureOperation(reactTag, callback));
}

public void enqueueMeasureInWindow(
final int reactTag,
final Callback callback) {
mOperations.add(
new MeasureInWindowOperation(reactTag, callback)
);
}

public void enqueueFindTargetForTouch(
final int reactTag,
final float targetX,
Expand Down

0 comments on commit b26f699

Please sign in to comment.