Câu trả lời:
Đây là một giải pháp, mặc dù các API thay đổi theo thời gian và có thể có các cách khác để thực hiện, hãy đảm bảo kiểm tra các câu trả lời khác. Một tuyên bố là nhanh hơn, và một tuyên bố khác là dễ dàng hơn.
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());
}
Cho tôi biết nếu nó hiệu quả.
Nó nên đệ quy chỉ cần thêm các vị trí trên cùng và bên trái từ mỗi container cha. Bạn cũng có thể thực hiện nó với Point
nếu bạn muốn.
API Android đã cung cấp một phương pháp để đạt được điều đó. Thử cái này:
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;
Đây là tài liệu
parentViewGroup
có thể là bất kỳ cha mẹ nào trong hệ thống phân cấp chế độ xem, vì vậy nó cũng hoạt động hoàn hảo cho ScrollView.
Vui lòng sử dụng view.getLocationOnScreen(int[] location);
(xem Javadocs ). Câu trả lời là trong mảng số nguyên (x = location[0]
và 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];
Đầu tiên tôi lấy bố cục gốc sau đó tính toán sự khác biệt tọa độ với khung nhìn.
Bạn cũng có thể sử dụng getLocationOnScreen()
thay thế getLocationInWindow()
.
Không cần phải tính toán bằng tay.
Chỉ cần sử dụng getGlobalVisibleRect như vậy:
Rect myViewRect = new Rect();
myView.getGlobalVisibleRect(myViewRect);
float x = myViewRect.left;
float y = myViewRect.top;
Cũng lưu ý rằng đối với tọa độ trung tâm, chứ không phải là:
...
float two = (float) 2
float cx = myViewRect.left + myView.getWidth() / two;
float cy = myViewRect.top + myView.getHeight() / two;
Bạn chỉ có thể làm:
float cx = myViewRect.exactCenterX();
float cy = myViewRect.exactCenterY();
getGlobalVisibleRect
là globalOffset.set(-mScrollX, -mScrollY);
vì vậy bạn chỉ có thể nhận được các giá trị đó getScollX/Y
nếu bạn chỉ cần các điều phối tương đối.
Bạn có thể sử dụng `
view.getLocationOnScreen (int [] location)
; `để có được vị trí của quan điểm của bạn một cách chính xác.
Nhưng có một nhược điểm nếu bạn sử dụng nó trước khi bố trí bị thổi phồng bạn sẽ nhận được vị trí sai.
Giải pháp cho vấn đề này là thêm ViewTreeObserver
như thế này: -
Khai báo toàn cầu mảng để lưu trữ vị trí xy của chế độ xem của bạn
int[] img_coordinates = new int[2];
và sau đó thêm ViewTreeObserver
vào bố cục cha mẹ của bạn để có được cuộc gọi lại cho lạm phát bố cục và chỉ sau đó tìm nạp vị trí của chế độ xem nếu không bạn sẽ nhận được tọa độ xy sai
// 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);
}
}
);
và sau đó sử dụng nó như thế này
xposition = img_coordinates[0];
yposition = img_coordinates[1];
Tôi đã tự viết cho mình hai phương pháp tiện ích dường như hoạt động trong hầu hết các điều kiện, xử lý cuộn, dịch và chia tỷ lệ, nhưng không xoay vòng. Tôi đã làm điều này sau khi thử sử dụng offsetDescendantRectToMyCoords () trong khung, có độ chính xác không nhất quán. Nó đã làm việc trong một số trường hợp nhưng cho kết quả sai ở những người khác.
"điểm" là một mảng nổi có hai phần tử (tọa độ x & y), "tổ tiên" là một nhóm xem ở đâu đó phía trên "hậu duệ" trong hệ thống phân cấp cây.
Đầu tiên một phương thức đi từ tọa độ con cháu đến tổ tiên:
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);
}
}
Tiếp theo nghịch đảo, từ tổ tiên đến hậu duệ:
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;
}
Trong trường hợp ai đó vẫn đang cố gắng để tìm ra điều này. Đây là cách bạn có được trung tâm X và Y của view
.
int pos[] = new int[2];
view.getLocationOnScreen(pos);
int centerX = pos[0] + view.getMeasuredWidth() / 2;
int centerY = pos[1] + view.getMeasuredHeight() / 2;
Tôi chỉ tìm thấy câu trả lời ở đây
Nó nói: Có thể truy xuất vị trí của một khung nhìn bằng cách gọi các phương thức getLeft () và getTop (). Cái trước trả về tọa độ bên trái, hoặc X, của hình chữ nhật đại diện cho khung nhìn. Cái sau trả về đỉnh, hoặc Y, tọa độ của hình chữ nhật đại diện cho khung nhìn. Các phương thức này đều trả về vị trí của khung nhìn so với cha của nó. Chẳng hạn, khi getLeft () trả về 20, điều đó có nghĩa là chế độ xem được đặt 20 pixel ở bên phải cạnh trái của cha mẹ trực tiếp.
nên sử dụng:
view.getLeft(); // to get the location of X from left to right
view.getRight()+; // to get the location of Y from right to left