Incorrect Coordinates From getLocationOnScreen/getLocationInWindow
Asked Answered
O

7

64

A call to getLocationOnScreen() or getLocationInWindow() both give me a top/Y coordinate that is about ~30px (status/notifications bar's height) too far down. The left/X coordinate is dead on.

As I hinted above, I believe the difference is because of the status/notification bar... I could be wrong. I think I can solve this if I can determine the size of the notification bar but, I'm having trouble doing just that.

Any help would be greatly appreciated.

Overflow answered 14/4, 2010 at 14:47 Comment(0)
O
86

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;
Overflow answered 3/5, 2010 at 21:3 Comment(3)
This worked in normal configuration, but if the activity adjusts 'globalView' height when SoftInput/Keyboard is opened, then keyboard height is also counted to 'topOffset', this results in wrong value for 'y'.Botryoidal
int [] locInWindow = new int [2]; globalView.getLocationInWindow(locInWindow); topOffset = locInWindow[1]; //Compute topOffset by getting Y coordinate of globalViewBotryoidal
@ThammeGowda could please explain more how i can get the top offset when the keyboard is openesTmesis
T
10

Here is how I like to get the status bar height, and adjust the offset:

final int[] location = new int[2];
anchor.getLocationInWindow(location); // Includes offset from status bar, *dumb*
Rect anchorRect = new Rect(location[0], location[1],
        location[0] + anchor.getWidth(), location[1] + anchor.getHeight());

anchor.getRootView().findViewById(android.R.id.content).getLocationInWindow(location);
int windowTopOffset = location[1];
anchorRect.offset(0, -windowTopOffset);
Tarlatan answered 30/8, 2012 at 21:44 Comment(5)
Why is it dumb that the location in window includes offset from status bar? You are asking for the location in window, so what else would you expect?Michikomichon
One would assume that the window is below the status bar, thus the offset wouldn't include the status bar height.Tarlatan
You're confusing Window with Screen I think.Ladon
windowTopOffset also includes the action bar's height, not only the status bar's.Windlass
This is working perfectly fine across all devices. compared to above answer.Thorny
S
4

I am having the same problem, try using

offset = myView.GetOffsetY();

and adjust your Y coord by that value, e.g.

coordY -= offset;

The class which offers the ``-method:

class MyView extends View {

  public int GetOffsetY() {
    int mOffset[] = new int[2];
    getLocationOnScreen( mOffset );
    return mOffset[1]; 
  }

}
Shilashilha answered 2/5, 2010 at 14:13 Comment(2)
I don't see "getOffsetY()". What class is that a method of?Overflow
I am sorry, I failed to post the method, in class MyView extends View { public int GetOffsetY() { int mOffset[] = new int[2]; getLocationOnScreen( mOffset ); return mOffset[1]; }Shilashilha
J
4

This answer does not include how to get the status bar height, but it does explain the behavior of getLocationOnScreen() and getLocationInWindow() returning the same value.

In the case of a normal activity (not a dialog) you should expect these two methods to return the same value. A Window lays out underneath (as in z-order not y coordinates) the status bar, so these methods cannot be used to determine the height of the status bar.

https://mcmap.net/q/58152/-getlocationonscreen-vs-getlocationinwindow

Jowers answered 22/11, 2013 at 21:16 Comment(1)
in Dialog view, it works fine if not set the window full screen is true, but if set as follows: <item name="android:windowFullscreen">true</item> then the value is not correct, so need subtract the 'topOffset'Flooded
T
1

As @ThammeGowda said that the correct answer will give incorrect position when the keyboard is shown but you still need to calculate the top offset of the action bar, so just get the action bar size directly

fun View.getPosition(): Point {
    val tv = TypedValue()
    if (context.theme.resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
        val actionBarHeight =
            TypedValue.complexToDimensionPixelSize(tv.data, resources.displayMetrics)

        val loc = IntArray(2).apply { getLocationInWindow(this) }

        val newY = loc[1] - actionBarHeight - (measuredHeight / 2) // to get the position in the middle of the view

        return Point(loc[0], newY)
    }
    return Point(0,0)
}

enter image description here

Tmesis answered 17/10, 2021 at 15:17 Comment(0)
C
0
 void setOffset(){
  int[] point1=new int[2];
  view1.getLocationInWindow(point1);
  
  int[] point2=new int[2];
  view2.getLocationInWindow(point2);

  int leftOffset=point2[0]-point1[0];
  int topOffset=point2[1]-point1[1];  
  // no need to call this function more than once
  // set the offset values in global variables 
  // remenber do't call it in OnCreate method
  // this helps to mesure all type of screen size
}

void setLocationOfView(){
  // now do your animation or any view to move
 int[] point =new int[2];
 sourceView.getLocationInWindow(point);
 view.setX(point[0]-leftOffset);
 view.setY(point[1]-topOffset);
 //wow you did it i am glad to help you and sorry for being late
}
Cq answered 26/3, 2022 at 20:57 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Adolf
B
0

Solution:

  1. Put an invisible png ImageView at the top with
android:layout_marginTop="0dp"
  1. Get location on screen of the invisible png. This will be your offset for the y-coordinate bug.
int[] location = new int[2];

invisiblepng.getLocationOnScreen(location);

int sourceY = location[1];

SharedPreferences.Editor editor = sp.edit();

editor.putString("compensateybug", Integer.toString(sourceY));

editor.apply();
 and
public static Point getLocationOnScreen(View view) {
int[] location = new int[2];
view.getLocationOnScreen(location);
return new Point(location[0], location[1]);
}
  1. Retrieve Y coordinate value of the "status/notification bar"
String compensateybug = sp.getString("compensateybug", "0");

int yourycoordinate = parseInt(compensateybug);

I have attached an invisible png image file for download at:

https://drive.google.com/file/d/1zxhP1r6ISvKG8Ig8iItDY2x6k5RVo4Nu/view?usp=sharing

Bursarial answered 20/6, 2022 at 5:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.