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

Android 获取视图';相对于根布局的s坐标,android,android-layout,coordinates,Android,Android Layout,Coordinates,我可以在Android中获取视图相对于我的活动根布局的x和y位置吗?这是一个解决方案,但由于API会随着时间的推移而变化,可能还有其他方法,请确保检查其他答案。一个声称更快,另一个声称更容易 private int getRelativeLeft(View myView) { if (myView.getParent() == myView.getRootView()) return myView.getLeft(); else return my

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

这是一个解决方案,但由于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());
}
让我知道这是否有效

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

请使用
查看.getLocationOnScreen(int[]位置)(请参阅)。答案在整数数组中(x=
位置[0]
和y=
位置[1]
)。

无需手动计算

就这样用吧:

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

...
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();
首先我得到根布局,然后计算与视图的坐标差。
您也可以使用
getLocationOnScreen()
而不是
getLocationInWindow()

我刚刚找到了答案

它说: 可以通过调用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

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;

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

“点”是一个带有两个元素(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;
}
你可以用`

view.GetLocationOn屏幕(int[]位置)

`以正确获取视图的位置

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

此问题的解决方案是添加
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];

万一有人还在想办法。这是获得
视图的中心X和Y的方法

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

您可以使用以下方法来了解父视图和您感兴趣的视图之间的差异:

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


getRelativeTop()这是需要添加强制转换的,但是当我添加(视图)或(按钮)((对象)myView.getParent()).getRelativeTop()时,它也是不对的。我做了一些非常类似的事情,但我通过getId==R.id.myRootView.Log.i(“RelativeLeft”,“”+getRelativeLeft(findViewById(R.id.tv)))检查根视图;Log.i(“RelativeTop”,“getRelativeTop”(findViewById(R.id.tv));我得到的都是0;布局中的textView如下:android api已经提供了根的相对坐标。每次我从这两个方法中得到返回值0时,请看这里。RelativeLayout中有一个单文本视图。这会将位置rlative返回到屏幕,而不是活动的根布局。还有View.getLocationInWindow(int[]),它返回视图相对于窗口的位置。您能确切地告诉我这个方法是如何工作的吗。它返回一个空值:如何在屏幕上获取视图的输出或x,y值要获取相对于根布局的位置,只需调用根布局和元素的getLocationInWindow,并使用减法的功能。它比公认的答案简单得多,而且可能更快。这只是与屏幕相关的位置。不是根。请阅读此处了解相对于root的内容:查看android源代码all
getGlobalVisibleRect
does
globalOffset.set(-mScrollX,-mScrollY)
因此,如果只需要相对坐标,您可以使用
getScollX/Y
获取这些值。这应该是可以接受的答案。getLocationOnScreen与getGlobalVisibleRect一样工作。但是getGlobalVisibleRect提供了更多的信息,不需要使用原始数组。因此,我选择getGlobalVisibleRect。用法很简单。Rect positionRect=新的Rect();view.getGlobalVisibleRect(positionRect)//x=positionRect.left//y=positionRect.top。如果孩子的某些部分在外面,在这种情况下不会考虑到这一点,那就欢呼吧。如何解决这种情况?答案很好!非常感谢你!这给出了相对于视图直接父视图的位置,而不是相对于根视图的位置,根视图可能是父视图的父视图等。缩放和旋转的视图是什么?这应该是可接受的答案。不可能出现堆栈溢出,也不可能出现数学错误。谢谢我同意,这应该是公认的答案——只剩下92票了。我想在工具栏中找到视图的坐标。这是一种对android始终如一的方法:fitsSystemWindows和19到27的各种API版本。谢谢你!这是正确的答案。工作得很好,只想提到
parentViewGroup
可以是视图层次结构中的任何父级,因此它可以完美地工作
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);
    });