Risposte:
Questa è una soluzione, anche se poiché le API cambiano nel tempo e potrebbero esserci altri modi per farlo, assicurati di controllare le altre risposte. Uno afferma di essere più veloce e un altro afferma di essere più semplice.
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());
}
Fammi sapere se funziona.
Dovrebbe ricorsivamente aggiungere le posizioni superiore e sinistra di ciascun contenitore principale. Potresti anche implementarlo con un Point
se lo desideri.
L'API Android fornisce già un metodo per raggiungere questo obiettivo. Prova questo:
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;
Ecco il documento
parentViewGroup
può essere qualsiasi genitore nella gerarchia della vista, quindi funziona perfettamente anche con ScrollView.
Si prega di utilizzare view.getLocationOnScreen(int[] location);
(consultare Javadocs ). La risposta è nell'array intero (x = location[0]
e 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];
Per prima cosa ottengo il layout di root, quindi calcolo la differenza di coordinate con la vista.
Puoi anche usare getLocationOnScreen()
invece di getLocationInWindow()
.
Non è necessario calcolarlo manualmente.
Usa getGlobalVisibleRect in questo modo:
Rect myViewRect = new Rect();
myView.getGlobalVisibleRect(myViewRect);
float x = myViewRect.left;
float y = myViewRect.top;
Nota anche che per le coordinate centrali, piuttosto che qualcosa di simile:
...
float two = (float) 2
float cx = myViewRect.left + myView.getWidth() / two;
float cy = myViewRect.top + myView.getHeight() / two;
Puoi semplicemente fare:
float cx = myViewRect.exactCenterX();
float cy = myViewRect.exactCenterY();
getGlobalVisibleRect
ciò che fa è in globalOffset.set(-mScrollX, -mScrollY);
modo da poter ottenere quei valori getScollX/Y
solo se hai solo bisogno dei relativi coodinati.
Puoi usare `
view.getLocationOnScreen (int [] location)
; `per ottenere correttamente la posizione della vista.
Ma c'è un fermo se lo si utilizza prima di layout è stato gonfiato otterrete posizione sbagliata.
La soluzione a questo problema sta aggiungendo in ViewTreeObserver
questo modo: -
Dichiarare globalmente l'array per memorizzare la posizione xy della vista
int[] img_coordinates = new int[2];
e quindi aggiungi ViewTreeObserver
il layout del tuo genitore per ottenere il callback per l'inflazione del layout e solo allora recupera la posizione della vista, altrimenti otterrai coordinate xy errate
// 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);
}
}
);
e poi usalo in questo modo
xposition = img_coordinates[0];
yposition = img_coordinates[1];
Mi sono scritto due metodi di utilità che sembrano funzionare nella maggior parte delle condizioni, gestendo scroll, traduzione e ridimensionamento, ma non rotazione. L'ho fatto dopo aver provato a usare offsetDescendantRectToMyCoords () nel framework, che aveva una precisione incoerente. Ha funzionato in alcuni casi, ma ha dato risultati sbagliati in altri.
"point" è un array float con due elementi (le coordinate x & y), "antenato" è un viewgroup da qualche parte sopra il "discendente" nella gerarchia dell'albero.
Innanzitutto un metodo che va dalle coordinate discendenti all'antenato:
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);
}
}
Quindi l'inverso, dall'antenato al discendente:
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;
}
Nel caso qualcuno stia ancora cercando di capirlo. Questo è come ottieni il centro X e Y del view
.
int pos[] = new int[2];
view.getLocationOnScreen(pos);
int centerX = pos[0] + view.getMeasuredWidth() / 2;
int centerY = pos[1] + view.getMeasuredHeight() / 2;
Ho appena trovato la risposta qui
Dice: è possibile recuperare la posizione di una vista richiamando i metodi getLeft () e getTop (). Il primo restituisce la coordinata sinistra, o X, del rettangolo che rappresenta la vista. Quest'ultimo restituisce la coordinata superiore, o Y, del rettangolo che rappresenta la vista. Questi metodi restituiscono entrambi la posizione della vista rispetto al suo genitore. Ad esempio, quando getLeft () restituisce 20, significa che la vista si trova 20 pixel a destra del bordo sinistro del suo genitore diretto.
quindi usa:
view.getLeft(); // to get the location of X from left to right
view.getRight()+; // to get the location of Y from right to left