问答中心分类: ANDROID如何获取视图的绝对坐标
0
匿名用户 提问 10小时 前

我试图得到视图左上角的绝对屏幕像素坐标。然而,我能找到的所有方法getLeft()getRight()不要工作,因为它们似乎都是相对于视图的父视图的,因此给了我0.正确的方法是什么?
如果有帮助的话,这是一个“把图片整理好”的游戏。我希望用户能够绘制一个框来选择多个作品。我的假设是,最简单的方法就是getRawX()getRawY()MotionEvent然后将这些值与放置这些部件的布局的左上角进行比较。知道了棋子的大小,我就可以确定选择了多少棋子。我意识到我可以getX()getY()MotionEvent,但这会返回一个相对位置,这使得确定选择了哪些工件变得更加困难。(我知道这不是不可能的,但它似乎太复杂了)。
编辑:根据其中一个问题,这是我用来尝试获取容器大小的代码。TableLayout是一张放着所有拼图的桌子。

TableLayout tableLayout = (TableLayout) findViewById(R.id.tableLayout);
Log.d(LOG_TAG, "Values " + tableLayout.getTop() + tableLayout.getLeft());

编辑2:下面是我尝试过的代码,下面是更多的建议答案。

public int[] tableLayoutCorners = new int[2];
(...)

TableLayout tableLayout = (TableLayout) findViewById(R.id.tableLayout);
tableLayout.requestLayout();
Rect corners = new Rect();
tableLayout.getLocalVisibleRect(corners);
Log.d(LOG_TAG, "Top left " + corners.top + ", " + corners.left + ", " + corners.right
            + ", " + corners.bottom);

cells[4].getLocationOnScreen(tableLayoutCorners);
Log.d(LOG_TAG, "Values " + tableLayoutCorners[0] + ", " + tableLayoutCorners[1]);

此代码是在所有初始化完成后添加的。图像已被分割为包含在TableLayout.单元格[0]位于左上角ImageView我选择了细胞[4 ],因为它在中间的某个地方,绝对不应该有(0,0)的坐标。
上面显示的代码仍然给出了日志中的所有0,我真的不明白,因为各种拼图都正确显示了。(我对tableLayoutCorners和默认可见性尝试了public int,两者的结果相同。)
我不知道这是否重要,但是ImageViews最初没有给出大小。大小ImageView在初始化过程中,当我给视图一个要显示的图像时,它会自动确定s。这是否会导致它们的值为0,即使日志代码是在它们获得图像并自动调整大小之后生成的?为了应对这种情况,我添加了代码tableLayout.requestLayout()如上所示,但这没有帮助。

10 Answers
0
Romain Guy 回答 10小时 前
Steve Haley 回复 10小时 前

这就是我希望找到的函数。不幸的是,我一定没有正确地使用它。我意识到getLocationOnScreen在Android v1中出现空指针异常是一个已知的错误。5(我编写代码的平台),但在v2中进行测试。我没有更好的表现。这两种方法都给了我0分。我在上面包含了一段代码片段。

Romain Guy 回复 10小时 前

你只能调用它之后布局已经发生了。在视图定位到屏幕上之前调用该方法。

Steve Haley 回复 10小时 前

啊哈,你说得对,虽然我没有那么做。谢谢对于任何想了解更多细节的人,我添加了一个答案来解释我的意思。

Peter Ajtai 回复 10小时 前

@史蒂夫-是的,必须进行w布局的呼叫排序(因为这些问题)非常重要,可能会导致一些非常恼人的错误。

Martin Marconcini 回复 10小时 前

现在,如果充气机或任何负责人提供一个回调,说:嘿,我完成了,所有视图都定位好了,那就太棒了。

Romain Guy 回复 10小时 前

你是说像ViewTreeObserver和它的OnGlobalLayoutListener?看风景。getViewTreeObserver()开始。

Martin Marconcini 回复 10小时 前

@罗曼圭:是的,有点像这样,但比必须注册(然后注销…)更容易混淆。这是一个iOS在SDK方面比Android做得更好的领域。我可以说,iOS每天都在使用这两种软件,有很多烦人的事情,但UIView处理并不是其中之一。:)

mr5 回复 10小时 前

@Romanguy抱歉,如果这真的很晚了,但是,在哪种情况下Activity这些计算应该完成吗?我明白了{0, 0}onCreate()但是,如果我把它放进去eventHandlerMethod()我明白了?

lilbyrdie 回复 10小时 前

@mr5:见下面西蒙的答案。您需要使用OnGlobalLayoutListener。到目前为止,这是确保在值准备就绪后调用这些函数的最简单方法。

benchuk 回复 10小时 前

将此信息与此信息一起使用:堆栈溢出。com/questions/7414065/…为绝对中心周围的缩放设置动画-在平移视图时很有用,而不是为其设置动画(例如,围绕新中心收缩生长)。

Pankaj Nimgade 回复 10小时 前

@Romanguy,我一直面临着和Stanly一样的问题,出于某种原因,我尝试的每种方法都给了我0。看来你已经明白为什么它给零了。我试图在布局加载后得到视图的坐标,但我还是得到零,为什么?谢谢你的帮助,堆栈溢出。com/questions/28622966/…

Pankaj Nimgade 回复 10小时 前

@罗曼圭,我怎么知道我的版面什么时候被完全加载了

William 回复 10小时 前

但两者之间的区别是什么?

Chad Bingham 回复 10小时 前

如果我试图定位的视图没有父视图,这仍然有效吗?

H. de Jonge 回复 10小时 前

注意:当视图旋转时,这会影响返回的坐标。我有一个旋转了-90°的正方形图像,返回的位置似乎是左下角的位置。我花了很长时间才弄明白这一点。

DKV 回复 10小时 前

@H.deJonge:你得到你的问题的答案了吗?

DKV 回复 10小时 前

@罗曼圭:旋转和缩放后是否可能得到中心

H. de Jonge 回复 10小时 前

@我只是把它包装在另一个视图中,用它来读取尺寸。

Nick Korostelev 回复 10小时 前

我刚刚注意到getLocationOnScreen没有考虑旋转。所以如果你真的看。设置旋转(180f),然后在屏幕上调用GetLocation,它将报告右上角坐标,而不是左上角坐标。

Nick Korostelev 回复 10小时 前

抱歉,我是说它会报告的右下角坐标而不是左上角。

Mohamad Rostami 回复 10小时 前

这不适用于滚动视图中的视图

0
Suragch 回答 10小时 前

被接受的答案实际上并没有告诉我们如何获取位置,所以这里有一个更详细的信息。你通过一个int长度为2的数组,值替换为视图的(x,y)坐标(左上角)。

int[] location = new int[2];
myView.getLocationOnScreen(location);
int x = location[0];
int y = location[1];

笔记

  • 替换getLocationOnScreen具有getLocationInWindow在大多数情况下应给出相同的结果(参见这个答案).但是,如果您使用的是较小的窗口,如对话框或自定义键盘,则需要选择更适合您需要的窗口。
  • 你会得到(0,0)如果你调用这个方法onCreate因为景观还没有布置好。你可以用ViewTreeObserver听布局完成后,你可以得到测量的坐标。(见这个答案.)
marticztn 回复 10小时 前

或者重写onWindowFocusChanged方法并在其中使用它

0
Naveen Murthy 回答 10小时 前

首先,必须获得视图的localVisible矩形
例如:

Rect rectf = new Rect();

//For coordinates location relative to the parent
anyView.getLocalVisibleRect(rectf);

//For coordinates location relative to the screen/display
anyView.getGlobalVisibleRect(rectf);

Log.d("WIDTH        :", String.valueOf(rectf.width()));
Log.d("HEIGHT       :", String.valueOf(rectf.height()));
Log.d("left         :", String.valueOf(rectf.left));
Log.d("right        :", String.valueOf(rectf.right));
Log.d("top          :", String.valueOf(rectf.top));
Log.d("bottom       :", String.valueOf(rectf.bottom));

希望这能有所帮助

Steve Haley 回复 10小时 前

这也应该奏效。。。然而,它也给了我0的值。我在上面附上了一段代码片段,如果这能帮助你找出我做错了什么。再次感谢。

Steve Haley 回复 10小时 前

见我的其他评论;我无意中在风景布置完之前就这么叫了。现在可以了谢谢。

Aniket 回复 10小时 前

@Naveen Murthy它为特定视图提供坐标,我需要根布局中单击视图的坐标。。

Jeffrey Blattman 回复 10小时 前

这将返回相对于父对象的位置。使用getGlobalVisibleRect()为了绝对的合作。

Pankaj Nimgade 回复 10小时 前

@史蒂夫海利,我一直面临着和你一样的问题,出于某种原因,我尝试的每一种方法都是0。看来你已经明白为什么它给零了。我试图在布局加载后得到视图的坐标,但我还是得到零,为什么?谢谢你的帮助

user5698345 回复 10小时 前

他返回了安卓的rect。R.id.内容。我怎样才能得到正确的德科维尤?

Dmitry 回复 10小时 前

它总是返回零。同时.getLocationOnScreen()作品但我也想知道宽度。

Rohit Kumar 回复 10小时 前

这个9.5年的答案完美无瑕。我需要它提供的左上右下的4个坐标,以及宽度和高度。谢谢

0
Simon 回答 10小时 前

使用全局布局侦听器对我来说一直都很好。它的优点是,如果布局发生变化,例如,如果某个东西被设置为查看,则可以重新测量。已删除或已添加/删除子视图。

public void onCreate(Bundle savedInstanceState)
{
     super.onCreate(savedInstanceState);

     // inflate your main layout here (use RelativeLayout or whatever your root ViewGroup type is
     LinearLayout mainLayout = (LinearLayout ) this.getLayoutInflater().inflate(R.layout.main, null); 

     // set a global layout listener which will be called when the layout pass is completed and the view is drawn
     mainLayout.getViewTreeObserver().addOnGlobalLayoutListener(
       new ViewTreeObserver.OnGlobalLayoutListener() {
          public void onGlobalLayout() {
               //Remove the listener before proceeding
               if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                    mainLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
               } else {
                    mainLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
               }

               // measure your views here
          }
       }
     );

     setContentView(mainLayout);
 }
MacD 回复 10小时 前

不要忘记在onGlobalLayout(){…}的内部(结尾)移除OnGlobalLayoutListener。另外,为了确定,请检查是否通过了!=0; 监听器可以被调用两次,一次调用w=0/h=0,第二次调用实际的、正确的值。

Mir-Ismaili 回复 10小时 前

用这种方法将主布局充气,然后使用setContentView()在特殊情况下引发了问题Activity在我的应用程序中!那是一个对话活动(windowFrame:@null, windowActionBar:false, windowIsFloating:true, windowNoTitle:true).其主要布局(a)LinearLayout)没有任何直接的孩子layout_width(他们都是match_parentwrap_content).

0
Amir Hossein Ghasemi 回答 10小时 前

第一种方式:
在里面Kotlin我们可以创建一个简单的视图扩展:

fun View.getLocationOnScreen(): Point
{
    val location = IntArray(2)
    this.getLocationOnScreen(location)
    return Point(location[0],location[1])
}

只需获得坐标:

val location = yourView.getLocationOnScreen()
val absX = location.x
val absY = location.y

第二种方式:
第二种方法更简单:

fun View.absX(): Int
{
    val location = IntArray(2)
    this.getLocationOnScreen(location)
    return location[0]
}

fun View.absY(): Int
{
    val location = IntArray(2)
    this.getLocationOnScreen(location)
    return location[1]
}

简单地得到X的绝对值view.absX()还有你view.absY()

Tuan Chau 回复 10小时 前

第一个样本的简短版本:val location = IntArray(2).apply(::getLocationOnScreen)