IT박스

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

itboxs 2020. 6. 30. 20:58
반응형

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


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]).


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

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


`를 사용할 수 있습니다

view.getLocationOnScreen (int [] 위치)

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

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

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

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

 int[] img_coordinates = new int[2];

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

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

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.

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

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

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.

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

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

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

참고URL : https://stackoverflow.com/questions/3619693/getting-views-coordinates-relative-to-the-root-layout

반응형