getLocationOnScreen()vs getLocationInWindow()

屏幕和视图在这两种方法的上下文有什么区别?

我有一个button,我想要得到它的中心的x坐标。

我想这足够了:

public int getButtonXPosition() { return (button.getLeft()+button.getRight())/2; } 

但是,如果我愿意的话,会有什么不同呢?

getLocationOnScreen()getLocationInWindow()

(当然,将button宽度的一半加上)

注意 – 这个答案在写的时候并不是被接受的答案,这就是为什么它是对另一个答案的反驳

我不认为接受的答案是正确的。 如果我创build一个新项目,并通过添加以下代码片段来仅编辑MainActivity:

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

我会看到打印到控制台108 108 。 这是使用运行4.3的Nexus 7。 我有类似的结果使用运行Android版本的仿真器早在2.2。

正常的活动窗口将有FILL_PARENTxFILL_PARENT作为它们的WindowManager.LayoutParams,这导致它们布局到整个屏幕的大小。 该窗口下面(关于z顺序,而不是y坐标)的状态栏和其他装饰,所以我相信一个更准确的图表将是:

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

如果逐步介绍这两个方法的源代码,您将看到getLocationInWindow遍历视图的视图层次结构直到RootViewImpl,总计视图坐标和减去父滚动偏移量。 在上面描述的情况下,ViewRootImpl从WindowSession获取状态栏高度,并通过fitSystemWindows传递给ActionBarOverlayLayout,该值将此值添加到操作栏高度。 然后,ActionBarOverlayLayout将此总和值应用到作为您的布局的父级的内容视图中,作为余量。

因此,您的内容布局低于状态栏,而不是窗口从较低的y坐标开始,而不是状态栏的结果,而是由于您的活动的内容视图中应用了余量。

如果你点击了getLocationOnScreen源代码,你会发现它只是调用getLocationInWindow ,然后添加Window的左边和上边的坐标(也被传递给ViewRootImpl的View,它从WindowSession中获取它们)。 在正常情况下,这些值都将为零。 在某些情况下,这些值可能不为零,例如放置在屏幕中间的对话窗口。


所以,总结一下:正常活动的窗口填满了整个屏幕,甚至是状态栏和装饰下的空间。 有问题的两个方法将返回相同的x和y坐标。 只有在特殊情况下,如窗口实际偏移的对话框,这两个值才会有所不同。

getLocationOnScreen()将获得基于手机屏幕的位置。

getLocationInWindow()将根据活动窗口获取位置。

对于正常活动 (不是全屏活动),与电话屏幕和活动窗口的关系如下:

| – 手机屏幕 ——————— |
| ——– 状态栏 ——————— |
| |
| ——————————————- |
| ——– 活动窗口 —— ——- |
| |
| |
| |
| |
| |
| |
| ——————————————- |

对于x坐标,这两种方法的值通常是相同的。

对于y坐标,这些值对于状态栏的高度有所不同