Respuestas:
Esta es una solución, aunque dado que las API cambian con el tiempo y puede haber otras formas de hacerlo, asegúrese de verificar las otras respuestas. Uno dice ser más rápido y otro dice ser más fácil.
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());
}
Avísame si eso funciona.
Debe agregar recursivamente las posiciones superior e izquierda de cada contenedor principal. También puede implementarlo con un Point
si lo desea.
La API de Android ya proporciona un método para lograrlo. Prueba esto:
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;
Aquí está el documento
parentViewGroup
puede ser cualquier padre en la jerarquía de vistas, por lo que también funciona perfectamente para ScrollView.
Por favor, use view.getLocationOnScreen(int[] location);
(ver Javadocs ). La respuesta está en la matriz de enteros (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];
Primero obtengo el diseño raíz y luego calculo la diferencia de coordenadas con la vista.
También puedes usar el en getLocationOnScreen()
lugar de getLocationInWindow()
.
No es necesario calcularlo manualmente.
Simplemente use getGlobalVisibleRect así:
Rect myViewRect = new Rect();
myView.getGlobalVisibleRect(myViewRect);
float x = myViewRect.left;
float y = myViewRect.top;
También tenga en cuenta que para las coordenadas del centro, en lugar de algo como:
...
float two = (float) 2
float cx = myViewRect.left + myView.getWidth() / two;
float cy = myViewRect.top + myView.getHeight() / two;
Solo puedes hacer:
float cx = myViewRect.exactCenterX();
float cy = myViewRect.exactCenterY();
getGlobalVisibleRect
hace es globalOffset.set(-mScrollX, -mScrollY);
para que pueda obtener esos valores getScollX/Y
si solo necesita las coordenadas relativas.
Puedes usar `
view.getLocationOnScreen (int [] ubicación)
; `para obtener la ubicación de su vista correctamente.
Pero hay una trampa si lo usa antes de diseño ha sido inflado obtendrá una posición incorrecta.
La solución a este problema es agregar ViewTreeObserver
así: -
Declare globalmente la matriz para almacenar la posición xy de su vista
int[] img_coordinates = new int[2];
y luego agregue ViewTreeObserver
su diseño principal para obtener una devolución de llamada para la inflación del diseño y solo entonces obtenga la posición de la vista, de lo contrario obtendrá coordenadas xy incorrectas
// 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);
}
}
);
y luego úsalo así
xposition = img_coordinates[0];
yposition = img_coordinates[1];
Escribí dos métodos de utilidad que parecen funcionar en la mayoría de las condiciones, manejo de desplazamiento, traslación y escalado, pero no rotación. Hice esto después de intentar usar offsetDescendantRectToMyCoords () en el marco, que tenía una precisión inconsistente. Funcionó en algunos casos pero dio resultados incorrectos en otros.
"punto" es una matriz flotante con dos elementos (las coordenadas x e y), "ancestro" es un grupo de vista en algún lugar por encima del "descendiente" en la jerarquía del árbol.
Primero, un método que va de coordenadas descendientes a ancestro:
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);
}
}
A continuación, el inverso, de antepasado a descendiente:
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;
}
En caso de que alguien todavía esté tratando de resolver esto. Así es como obtienes el 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;
Acabo de encontrar la respuesta aquí
Dice: Es posible recuperar la ubicación de una vista invocando los métodos getLeft () y getTop (). El primero devuelve la coordenada izquierda o X del rectángulo que representa la vista. Este último devuelve la coordenada superior o Y del rectángulo que representa la vista. Estos dos métodos devuelven la ubicación de la vista en relación con su padre. Por ejemplo, cuando getLeft () devuelve 20, eso significa que la vista se encuentra a 20 píxeles a la derecha del borde izquierdo de su padre directo.
entonces 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