[android] 루트 레이아웃을 기준으로 뷰의 좌표 얻기

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

그것이 작동하는지 알려주세요.

각 상위 컨테이너에서 상단 및 왼쪽 위치를 반복적으로 추가해야합니다. 원한다면 그것을 사용하여 구현할 수도 있습니다 Point.


답변

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;

여기 의사가 있습니다


답변

사용 view.getLocationOnScreen(int[] location);하십시오 ( Javadocs 참조 ). 답은 정수 배열에 있습니다 (x = location[0]및 y = location[1]).


답변

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()


답변

수동으로 계산할 필요가 없습니다.

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


답변

`를 사용할 수 있습니다

view.getLocationOnScreen (int [] 위치)

;`보기의 위치를 ​​올바르게 얻으려면.

그러나 캐치가 있습니다 레이아웃이 팽창하기 전에 그것을 사용하면 가 발생하여 잘못된 위치를 얻을 수 있습니다.

이 문제에 대한 해결책은 ViewTreeObserver 과 같습니다.

xy 위치를 저장할 배열을 전역 적으로 선언하십시오.

 int[] img_coordinates = new int[2];

그런 다음 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);
                        }
                    }
            );

다음과 같이 사용하십시오

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


답변

나는 스크롤, 변환 및 스케일링을 처리하지만 회전이 아닌 대부분의 조건에서 작동하는 것처럼 보이는 두 가지 유틸리티 방법을 스스로 작성했습니다. 일관성이없는 프레임 워크에서 offsetDescendantRectToMyCoords ()를 사용하려고 시도한 후에이 작업을 수행했습니다. 어떤 경우에는 효과가 있었지만 다른 결과에서는 잘못된 결과를 냈습니다.

“point”는 두 개의 요소 (x & y 좌표)를 가진 float 배열이고 “ancestor”는 트리 계층에서 “descendant”위의 뷰 그룹입니다.

먼저 자손 좌표에서 조상으로가는 방법 :

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