Ela*_*nda 63 java android screen view
在这两种方法的上下文中,屏幕和视图有什么区别?
我有一个按钮,我想得到它的中心的x坐标.
我想这就足够了:
public int getButtonXPosition() {
return (button.getLeft()+button.getRight())/2;
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我使用它会有什么不同
getLocationOnScreen()
还是getLocationInWindow()
?
(当然,添加按钮宽度的一半)
gro*_*cho 111
我不认为这个答案是正确的.如果我创建一个新项目,并通过添加以下代码段仅编辑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);
}
Run Code Online (Sandbox Code Playgroud)
我会看到打印到控制台108 108
.这是使用运行4.3的Nexus 7.我有类似的结果使用运行Android版本的模拟器早在2.2.
正常活动窗口将具有FILL_PARENTxFILL_PARENT作为其WindowManager.LayoutParams,这将导致它们布局为整个屏幕的大小.窗口布局在下面(关于z顺序,而不是y坐标)状态栏和其他装饰,所以我相信更准确的图表将是:
|--phone screen-----activity window---|
|--------status bar-------------------|
| |
| |
|-------------------------------------|
Run Code Online (Sandbox Code Playgroud)
如果单步执行这两种方法的源代码,您将看到getLocationInWindow
遍历视图的视图层次结构直到RootViewImpl,求和视图坐标并减去父滚动偏移.在上面描述的情况下,ViewRootImpl从WindowSession获取状态栏高度,并通过fitSystemWindows向下传递给ActionBarOverlayLayout,后者将此值添加到操作栏高度.然后ActionBarOverlayLayout获取此求和值并将其作为边距应用于其内容视图(布局的父级).
因此,您的内容布局低于状态栏,而不是因为窗口从较低的y坐标开始而不是状态栏,而是由于边距应用于您的活动的内容视图.
如果您getLocationOnScreen
查看源代码,您将看到它只是调用getLocationInWindow
,然后添加Window的左侧和顶部coords(它们也通过ViewRootImpl传递给View,它从WindowSession中获取它们).在正常情况下,这些值都将为零.在某些情况下,这些值可能不为零,例如放置在屏幕中间的对话窗口.
因此,总结一下:正常活动的窗口填满整个屏幕,甚至是状态栏和装饰下的空间.有问题的两种方法将返回相同的x和y坐标.只有在窗口实际偏移的对话框等特殊情况下,这两个值才会不同.
Iva*_*van 24
getLocationOnScreen()将根据手机屏幕获取位置.
getLocationInWindow()将根据活动窗口获取位置.
对于正常活动(非全屏活动),与电话屏幕和活动窗口的关系如下:
| - 手机屏幕 --------------------- |
| -------- 状态栏 --------------------- |
| |
| ------------------------------------------- |
| -------- 活动窗口 ------ ------- |
| |
| |
| |
| |
| |
| |
| ------------------------------------------- |
对于x坐标,两种方法的值通常相同.
对于y坐标,值与状态栏的高度有所不同
对于getLocationOnScreen()
,x
和y
将返回视图的左上角。
使用getLocationInWindow()
将相对于其容器,而不是整个屏幕。getLocationOnScreen()
这与您的根布局小于屏幕(如在对话框中)不同。在大多数情况下,它们是相同的。
注意:如果值始终为 0,您可能会在请求位置之前立即更改视图。您可以使用view.post确保值可用
int[] point = new int[2];
view.getLocationOnScreen(point); // or getLocationInWindow(point)
int x = point[0];
int y = point[1];
Run Code Online (Sandbox Code Playgroud)
为了确保视图有机会更新,请在使用以下方法计算视图的新布局后运行您的位置请求view.post
:
view.post(() -> {
// Values should no longer be 0
int[] point = new int[2];
view.getLocationOnScreen(point); // or getLocationInWindow(point)
int x = point[0];
int y = point[1];
});
Run Code Online (Sandbox Code Playgroud)
~~
val point = IntArray(2)
view.getLocationOnScreen(point) // or getLocationInWindow(point)
val (x, y) = point
Run Code Online (Sandbox Code Playgroud)
为了确保视图有机会更新,请在使用以下方法计算视图的新布局后运行您的位置请求view.post
:
view.post {
// Values should no longer be 0
val point = IntArray(2)
view.getLocationOnScreen(point) // or getLocationInWindow(point)
val (x, y) = point
}
Run Code Online (Sandbox Code Playgroud)
我建议创建一个扩展函数来处理这个问题:
// To use, call:
val (x, y) = view.screenLocation
val View.screenLocation get(): IntArray {
val point = IntArray(2)
getLocationOnScreen(point)
return point
}
Run Code Online (Sandbox Code Playgroud)
如果您需要可靠性,还可以添加:
// To use, call:
view.screenLocationSafe { x, y -> Log.d("", "Use $x and $y here") }
fun View.screenLocationSafe(callback: (Int, Int) -> Unit) {
post {
val (x, y) = screenLocation
callback(x, y)
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
57044 次 |
最近记录: |