获取相对于根布局的View坐标

时间:2010-09-01 15:28:00

标签: android android-layout coordinates

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

10 个答案:

答案 0 :(得分:132)

这是一种解决方案,但由于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());
}

如果有效,请告诉我。

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

答案 1 :(得分:111)

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;

以下是doc

答案 2 :(得分:91)

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

答案 3 :(得分:33)

无需手动计算。

像这样使用getGlobalVisibleRect

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

另请注意,对于中心坐标,而不是像:

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

你可以这样做:

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

答案 4 :(得分:32)

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];

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

答案 5 :(得分:6)

你可以使用`

  

view.getLocationOnScreen(int [] location)

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

但是如果你在布局膨胀之前使用它会有一个 catch 你会得到错误的位置。

此问题的解决方法是添加ViewTreeObserver,如下所示: -

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

 int[] img_coordinates = new int[2];

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

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

然后像这样使用它

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

答案 6 :(得分:2)

我自己编写了两个实用程序方法,它们似乎在大多数条件下工作,处理滚动,平移和缩放,但不是旋转。我在尝试在框架中使用offsetDescendantRectToMyCoords()之后做了这个,它具有不一致的准确性。它在某些情况下起作用,但在其他情况下却产生了错

"点"是一个带有两个元素(x& y坐标)的浮点数组,"祖先"是一个视图组,位于"后代"之上。在树层次结构中。

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

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

接下来,从祖先到后代:

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

答案 7 :(得分:1)

我刚刚找到答案here

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

所以使用:

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

答案 8 :(得分:1)

有人还在试图解决这个问题。这是你得到view的中心X和Y的方法。

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

答案 9 :(得分:0)

您可以使用以下命令获取父视图和您感兴趣的视图之间的区别:

private int getRelativeTop(View view) {
    final View parent = (View) view.getParent();
    int[] parentLocation = new int[2];
    int[] viewLocation = new int[2];

    view.getLocationOnScreen(viewLocation);
    parent.getLocationOnScreen(parentLocation);

    return viewLocation[1] - parentLocation[1];
}

绘制视图后不要忘记调用它:

 timeIndicator.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
        final int relativeTop = getRelativeTop(timeIndicator);
    });