Відповіді:
Це одне рішення, хоча оскільки 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;
Ось док
parentViewGroup
в ієрархії перегляду може бути будь-який батько, тому він прекрасно працює і для ScrollView.
Будь ласка, використовуйте 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();
getGlobalVisibleRect
це globalOffset.set(-mScrollX, -mScrollY);
так, щоб ви могли просто отримати ці значення, getScollX/Y
якщо вам потрібні лише відносні кодинати.
Ви можете використовувати `
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 () у рамках, який мав непослідовну точність. У деяких випадках це спрацьовувало, але в інших дало неправильні результати.
"точка" - це поплавковий масив з двома елементами (координати 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;
}
Скрізь, хтось все ще намагається це зрозуміти. Це, як ви отримаєте центр X і Y з view
.
int pos[] = new int[2];
view.getLocationOnScreen(pos);
int centerX = pos[0] + view.getMeasuredWidth() / 2;
int centerY = pos[1] + view.getMeasuredHeight() / 2;
Я щойно знайшов відповідь тут
У ній написано: Можна отримати місце перегляду, скориставшись методами 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