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