Android 获取视图相对于根布局的坐标

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3619693/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 11:01:02  来源:igfitidea点击:

Getting View's coordinates relative to the root layout

androidandroid-layoutcoordinates

提问by fhucho

Can I get a View's x and y position relative to the root layout of my Activity in Android?

我可以在 Android 中获得相对于我的 Activity 根布局的视图的 x 和 y 位置吗?

采纳答案by ramblinjan

This is one solution, though since APIs change over time and there may be other ways of doing it, make sure to check the other answers. One claims to be faster, and another claims to be easier.

这是一种解决方案,但由于 API 会随着时间的推移而变化,并且可能还有其他方法,请务必检查其他答案。一个声称更快,另一个声称更容易。

private int getRelativeLeft(View myView) {
    if (myView.getParent() == myView.getRootView())
        return myView.getLeft();
    else
        return myView.getLeft() + getRelativeLeft((View) myView.getParent());
}

private int getRelativeTop(View myView) {
    if (myView.getParent() == myView.getRootView())
        return myView.getTop();
    else
        return myView.getTop() + getRelativeTop((View) myView.getParent());
}

Let me know if that works.

让我知道这是否有效。

It should recursively just add the top and left positions from each parent container. You could also implement it with a Pointif you wanted.

它应该递归地添加每个父容器的顶部和左侧位置。如果需要,您也可以使用 a 来实现它Point

回答by carlo.marinangeli

The Android API already provides a method to achieve that. Try this:

Android API 已经提供了一种方法来实现这一点。尝试这个:

Rect offsetViewBounds = new Rect();
//returns the visible bounds
childView.getDrawingRect(offsetViewBounds);
// calculates the relative coordinates to the parent
parentViewGroup.offsetDescendantRectToMyCoords(childView, offsetViewBounds); 

int relativeTop = offsetViewBounds.top;
int relativeLeft = offsetViewBounds.left;

Here is the doc

这是文档

回答by BinaryTofu

Please use view.getLocationOnScreen(int[] location);(see Javadocs). The answer is in the integer array (x = location[0]and y = location[1]).

请使用view.getLocationOnScreen(int[] location);(参见Javadocs)。答案在整数数组中(x =location[0]和 y = location[1])。

回答by TalL

No need to calculate it manually.

无需手动计算。

Just use getGlobalVisibleRectlike so:

只需像这样使用getGlobalVisibleRect

Rect myViewRect = new Rect();
myView.getGlobalVisibleRect(myViewRect);
float x = myViewRect.left;
float y = myViewRect.top;

Also note that for the centre coordinates, rather than something like:

还要注意,对于中心坐标,而不是类似的东西:

...
float two = (float) 2
float cx = myViewRect.left + myView.getWidth() / two;
float cy = myViewRect.top + myView.getHeight() / two;

You can just do:

你可以这样做:

float cx = myViewRect.exactCenterX();
float cy = myViewRect.exactCenterY();

回答by Kerrmiter

View rootLayout = view.getRootView().findViewById(android.R.id.content);

int[] viewLocation = new int[2]; 
view.getLocationInWindow(viewLocation);

int[] rootLocation = new int[2];
rootLayout.getLocationInWindow(rootLocation);

int relativeLeft = viewLocation[0] - rootLocation[0];
int relativeTop  = viewLocation[1] - rootLocation[1];

First I get the root layout then calculate the coordinates difference with the view.
You can also use the getLocationOnScreen()instead of getLocationInWindow().

首先我得到根布局,然后计算与视图的坐标差异。
您也可以使用getLocationOnScreen()代替getLocationInWindow()

回答by Hitesh Sahu

You can use `

你可以使用`

view.getLocationOnScreen(int[] location)

view.getLocationOnScreen(int[] 位置)

;` to get location of your view correctly.

;` 以正确获取您的视图位置。

But there is a catchif you use it before layout has been inflated you will get wrong position.

但有一个捕获如果你使用它之前的布局已经膨胀,你会得到错误的位置。

Solution to this problem is adding ViewTreeObserverlike this :-

这个问题的解决方案是这样添加的ViewTreeObserver:-

Declare globally the array to store x y position of your view

全局声明数组以存储视图的 xy 位置

 int[] img_coordinates = new int[2];

and then add ViewTreeObserveron your parent layout to get callback for layout inflation and only then fetch position of view otherwise you will get wrong x y coordinates

然后添加ViewTreeObserver您的父布局以获得布局膨胀的回调,然后才获取视图位置,否则您将得到错误的 xy 坐标

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

                            // measure your views here
                            fab.getLocationOnScreen(img_coordinates);
                        }
                    }
            );

and then use it like this

然后像这样使用它

xposition = img_coordinates[0];
yposition =  img_coordinates[1];

回答by Alexander Hugestrand

I wrote myself two utility methods that seem to work in most conditions, handling scroll, translation and scaling, but not rotation. I did this after trying to use offsetDescendantRectToMyCoords() in the framework, which had inconsistent accuracy. It worked in some cases but gave wrong results in others.

我自己写了两个实用方法,它们似乎在大多数情况下都有效,处理滚动、平移和缩放,但不能处理旋转。我是在尝试在框架中使用 offsetDescendantRectToMyCoords() 之后这样做的,但它的准确性不一致。它在某些情况下有效,但在其他情况下却给出了错误的结果。

"point" is a float array with two elements (the x & y coordinates), "ancestor" is a viewgroup somewhere above the "descendant" in the tree hierarchy.

“point”是一个具有两个元素(x 和 y 坐标)的浮点数组,“祖先”是树层次结构中“后代”上方某处的视图组。

First a method that goes from descendant coordinates to ancestor:

首先是从后代坐标到祖先的方法:

public static void transformToAncestor(float[] point, final View ancestor, final View descendant) {
    final float scrollX = descendant.getScrollX();
    final float scrollY = descendant.getScrollY();
    final float left = descendant.getLeft();
    final float top = descendant.getTop();
    final float px = descendant.getPivotX();
    final float py = descendant.getPivotY();
    final float tx = descendant.getTranslationX();
    final float ty = descendant.getTranslationY();
    final float sx = descendant.getScaleX();
    final float sy = descendant.getScaleY();

    point[0] = left + px + (point[0] - px) * sx + tx - scrollX;
    point[1] = top + py + (point[1] - py) * sy + ty - scrollY;

    ViewParent parent = descendant.getParent();
    if (descendant != ancestor && parent != ancestor && parent instanceof View) {
        transformToAncestor(point, ancestor, (View) parent);
    }
}

Next the inverse, from ancestor to descendant:

接下来是逆向,从祖先到后代:

public static void transformToDescendant(float[] point, final View ancestor, final View descendant) {
    ViewParent parent = descendant.getParent();
    if (descendant != ancestor && parent != ancestor && parent instanceof View) {
        transformToDescendant(point, ancestor, (View) parent);
    }

    final float scrollX = descendant.getScrollX();
    final float scrollY = descendant.getScrollY();
    final float left = descendant.getLeft();
    final float top = descendant.getTop();
    final float px = descendant.getPivotX();
    final float py = descendant.getPivotY();
    final float tx = descendant.getTranslationX();
    final float ty = descendant.getTranslationY();
    final float sx = descendant.getScaleX();
    final float sy = descendant.getScaleY();

    point[0] = px + (point[0] + scrollX - left - tx - px) / sx;
    point[1] = py + (point[1] + scrollY - top - ty - py) / sy;
}

回答by Sheraz Ahmad Khilji

Incase someone is still trying to figure this out. This is how you get the center X and Y of the view.

以防万一有人仍在试图解决这个问题。这就是你如何获得view.

    int pos[] = new int[2];
    view.getLocationOnScreen(pos);
    int centerX = pos[0] + view.getMeasuredWidth() / 2;
    int centerY = pos[1] + view.getMeasuredHeight() / 2;

回答by donmj

I just found the answer here

我刚刚在这里找到答案

It says: It is possible to retrieve the location of a view by invoking the methods getLeft() and getTop(). The former returns the left, or X, coordinate of the rectangle representing the view. The latter returns the top, or Y, coordinate of the rectangle representing the view. These methods both return the location of the view relative to its parent. For instance, when getLeft() returns 20, that means the view is located 20 pixels to the right of the left edge of its direct parent.

它说:可以通过调用方法 getLeft() 和 getTop() 来检索视图的位置。前者返回表示视图的矩形的左坐标或 X 坐标。后者返回表示视图的矩形的顶部坐标或 Y 坐标。这些方法都返回视图相对于其父级的位置。例如,当 getLeft() 返回 20 时,这意味着视图位于其直接父级左边缘右侧 20 像素处。

so use:

所以使用:

view.getLeft(); // to get the location of X from left to right
view.getRight()+; // to get the location of Y from right to left