Odpowiedzi:
Jest to jedno rozwiązanie, ale ponieważ interfejsy API zmieniają się w czasie i mogą istnieć inne sposoby, aby to zrobić, sprawdź pozostałe odpowiedzi. Jeden twierdzi, że jest szybszy, a inny twierdzi, że jest łatwiejszy.
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());
}
Daj znać, jeśli to zadziała.
Powinien rekurencyjnie po prostu dodać górną i lewą pozycję z każdego kontenera nadrzędnego. Możesz również zaimplementować to za pomocą, Point
jeśli chcesz.
Interfejs API systemu Android już zapewnia metodę, aby to osiągnąć. Spróbuj tego:
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;
Oto doktor
parentViewGroup
może to być dowolny element nadrzędny w hierarchii widoków, więc działa również doskonale dla ScrollView.
Użyj view.getLocationOnScreen(int[] location);
(patrz Javadocs ). Odpowiedź znajduje się w tablicy liczb całkowitych (x = location[0]
i 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];
Najpierw otrzymuję układ główny, a następnie obliczam różnicę współrzędnych w stosunku do widoku.
Możesz także użyć getLocationOnScreen()
zamiast getLocationInWindow()
.
Nie ma potrzeby ręcznego obliczania.
Po prostu użyj getGlobalVisibleRect w następujący sposób:
Rect myViewRect = new Rect();
myView.getGlobalVisibleRect(myViewRect);
float x = myViewRect.left;
float y = myViewRect.top;
Zauważ również, że dla współrzędnych środka, a nie czegoś takiego:
...
float two = (float) 2
float cx = myViewRect.left + myView.getWidth() / two;
float cy = myViewRect.top + myView.getHeight() / two;
Możesz po prostu zrobić:
float cx = myViewRect.exactCenterX();
float cy = myViewRect.exactCenterY();
getGlobalVisibleRect
to robi, globalOffset.set(-mScrollX, -mScrollY);
więc możesz po prostu uzyskać te wartości, getScollX/Y
jeśli potrzebujesz tylko względnych współrzędnych.
Możesz użyć rozszerzenia `
view.getLocationOnScreen (int [] lokalizacja)
; `aby uzyskać poprawne położenie widoku.
Ale jest pewien haczyk, jeśli użyjesz go przed nadmuchaniem układu, uzyskasz niewłaściwą pozycję.
Rozwiązaniem tego problemu jest dodanie w ViewTreeObserver
ten sposób: -
Globalnie zadeklaruj tablicę do przechowywania pozycji xy widoku
int[] img_coordinates = new int[2];
a następnie dodaj ViewTreeObserver
swój układ nadrzędny, aby uzyskać wywołanie zwrotne dla inflacji układu i dopiero wtedy pobierz pozycję widoku, w przeciwnym razie otrzymasz błędne współrzędne 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);
}
}
);
a następnie użyj go w ten sposób
xposition = img_coordinates[0];
yposition = img_coordinates[1];
Napisałem sobie dwie metody narzędziowe, które wydają się działać w większości warunków, obsługując przewijanie, tłumaczenie i skalowanie, ale nie rotację. Zrobiłem to po próbie użycia offsetDescendantRectToMyCoords () we frameworku, który miał niespójną dokładność. W niektórych przypadkach działało, ale w innych dawało złe wyniki.
„point” to tablica zmiennoprzecinkowa z dwoma elementami (współrzędne x & y), „przodek” to grupa widoku gdzieś powyżej „potomka” w hierarchii drzewa.
Najpierw metoda, która przechodzi od współrzędnych potomnych do przodków:
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);
}
}
Dalej odwrotnie, od przodka do potomka:
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;
}
O ile ktoś wciąż próbuje to rozgryźć. W ten sposób otrzymujesz środek X i Y elementu view
.
int pos[] = new int[2];
view.getLocationOnScreen(pos);
int centerX = pos[0] + view.getMeasuredWidth() / 2;
int centerY = pos[1] + view.getMeasuredHeight() / 2;
Właśnie znalazłem odpowiedź tutaj
Mówi: Możliwe jest pobranie lokalizacji widoku przez wywołanie metod getLeft () i getTop (). Pierwsza z nich zwraca lewą, czyli X, współrzędną prostokąta reprezentującego widok. Ta ostatnia zwraca górną, czyli Y, współrzędną prostokąta reprezentującego widok. Obie te metody zwracają położenie widoku względem jego elementu nadrzędnego. Na przykład, gdy getLeft () zwraca 20, oznacza to, że widok znajduje się 20 pikseli na prawo od lewej krawędzi swojego bezpośredniego rodzica.
więc użyj:
view.getLeft(); // to get the location of X from left to right
view.getRight()+; // to get the location of Y from right to left