Getlocationonscreen() VS Getlocationinwindow()

getLocationOnScreen() vs getLocationInWindow()

I don't think this answer is correct. If I create a new project, and edit only the MainActivity by adding the following snippet:

public boolean dispatchTouchEvent(MotionEvent ev) {
View contentsView = findViewById(android.R.id.content);

int test1[] = new int[2];
contentsView.getLocationInWindow(test1);

int test2[] = new int[2];
contentsView.getLocationOnScreen(test2);

System.out.println(test1[1] + " " + test2[1]);

return super.dispatchTouchEvent(ev);
}

I will see printed to the console 108 108. This is using a Nexus 7 running 4.3. I have similar results using emulators running android versions as far back as 2.2.

Normal activity windows will have FILL_PARENTxFILL_PARENT as their WindowManager.LayoutParams, which results in them laying out to the size of the entire screen. The Window is laid out underneath (in regards to z-order, not y-coordinates) the statusbar and other decorations, so I believe a more accurate chart would be:

|--phone screen-----activity window---| 
|--------status bar-------------------|
| |
| |
|-------------------------------------|

If you step through the source of these two methods, you will see that getLocationInWindow traverses up your view's view hierarchy up to the RootViewImpl, summing view coordinates and
subtracting parent scroll offsets. In the case I described above the ViewRootImpl is getting the status bar height from the WindowSession, and passing it down through fitSystemWindows to the ActionBarOverlayLayout, which adds this value to the actionbar height. ActionBarOverlayLayout then takes this summed value and applies it to its content view, which is the parent of your layout, as a margin.

So, your content is laid out lower than the status bar not as a result of the window starting at a lower y coordinate than the status bar, but instead as a result of a margin being applied to your activity's content view.

If you peer into the getLocationOnScreen source you'll see it merely calls getLocationInWindow and then adds the Window's left and top coords (which are also passed to the View by ViewRootImpl, which fetches them from the WindowSession). In the normal case, these values will both be zero. There are some situations where these values may be non-zero, for example a dialog window that is placed in the middle of the screen.


So, to summarize: A normal activity's window fills the entire screen, even the space under the status bar and decorations. The two methods in question will return the same x and y coordinates. Only in special cases such as dialogs where the Window is actually offset will these two values differ.

Incorrect Coordinates From getLocationOnScreen/getLocationInWindow

I ended up solving this issue by determining the height of the status/notification bar like so:

View globalView = ...; // the main view of my activity/application

DisplayMetrics dm = new DisplayMetrics();
this.getWindowManager().getDefaultDisplay().getMetrics(dm);
int topOffset = dm.heightPixels - globalView.getMeasuredHeight();

View tempView = ...; // the view you'd like to locate
int[] loc = new int[2];
tempView.getLocationOnScreen(loc);

final int y = loc[1] - topOffset;

Why are getLocationOnScreen() and getLocationInWindow() returning same values?

I was confused by this as well, so I did a bit of investigation that I summarize
here.

Basically, the window lays out beneath the status bar (beneath in regards to z-order not y-coordinates), and fills the entire screen, in most cases. So, in a normal activity you should expect these methods to return the same values. Only in unique cases, such as dialogs where the Window is actually offset, will you see these methods returning different values.

What is location of getLocationOnScreen return for?

it is exact return for left,top coordinates of that view. I get wrong value because my view still not rendered before i call view.getLocationOnScreen(location).

What are the units and axes directions for View.getLocationOnScreen ()?

getLocationOnScreen() returns coordinates relative to the screen (you can think of this as absolute position). They are in pixels, the origin is top left, X axes increases to the right, and Y axes increases to down that's true for either orientation (portrait or landscape). On a screen that is 320x480 they are:

  • top left = 0, 0
  • bottom left = 0, 480
  • top right = 320, 0
  • bottom right 320, 480

The other method getLocationInWindow() returns coordinates relative to the parent window (say a dialog, or something like that). The coordinate system doesn't change, although the extents of what the range is depends on the size of the window your view is contained within.

Set position of view not based on its parent

Both getLocationOnScreen() & getLocationInWindow() are almost same, except that getLocationOnScreen() returns the coordinates relative to the whole screen while getLocationInWindow() will return the coordinates relative to the activity. See here

You are not getting the proper coordinates, even though your are using correct methods. Probably, this should resolve your query.

How to get exact position in pixels of my TextView?

I have a smartphone of 2560 x 1440 px... My TextView is pretty much in the middle of the screen, so supposedly at (1280,770).

Not correct, unless you talk about the center of the TextView. Any view is rendered on screen within its rectangle, so its coordinates are considered to be of [left, top, right, bottom].

The GetLocationInWindow() method returns (left, top) coordinates of a view. So (x = 69, y = 1111) looks to be meaningful for the left top corner of your TextView located in the middle of screen.

Important note: GetLocationInWindow() returns the coordinates w.r.t the root view, not actual window. You should take the status bar height into consideration. And here is how you can calculate Height of status bar in Android.



Related Topics



Leave a reply



Submit