android - programacion - Obtener las coordenadas de View relativas al diseño de la raíz
manual de android en pdf (9)
¿Puedo obtener una posición xey de Vista en relación con el diseño raíz de mi Actividad en Android?
Acabo de encontrar la respuesta here
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 métodos devuelven la ubicación de la vista en relación con su elemento principal. 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 elemento primario directo.
así que 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
En caso de que alguien todavía esté tratando de resolver esto. Así es como obtienes el centro X e Y de la view
.
int pos[] = new int[2];
view.getLocationOnScreen(pos);
int centerX = pos[0] + view.getMeasuredWidth() / 2;
int centerY = pos[1] + view.getMeasuredHeight() / 2;
Esta es una solución, sin embargo, dado que las API cambian con el tiempo y puede haber otras formas de hacerlo, asegúrese de verificar las otras respuestas. Uno afirma ser más rápido y otro afirma 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.
Debería recursivamente agregar las posiciones superior e izquierda de cada contenedor principal. También podrías implementarlo con un Point
si lo deseas.
La API de Android ya proporciona un método para lograr eso. 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 doc
Me escribí dos métodos de utilidad que parecen funcionar en la mayoría de las condiciones, manejo de desplazamiento, traducción y escalado, pero no rotación. Lo hice después de intentar usar offsetDescendantRectToMyCoords () en el marco, que tenía una precisión inconsistente. Funcionó en algunos casos, pero dio resultados erróneos 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 de árbol.
Primero, un método que va desde las coordenadas descendentes hasta el 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);
}
}
Luego el inverso, de ancestro 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;
}
No es necesario calcularlo manualmente.
Simplemente use getGlobalVisibleRect forma:
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 así como:
...
float two = (float) 2
float cx = myViewRect.left + myView.getWidth() / two;
float cy = myViewRect.top + myView.getHeight() / two;
Puedes hacer:
float cx = myViewRect.exactCenterX();
float cy = myViewRect.exactCenterY();
Puedes usar `
view.getLocationOnScreen (int [] ubicación)
; `para obtener la ubicación de su vista correctamente.
Pero hay una trampa si la usa antes de que el diseño se haya 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
en su diseño principal para obtener una devolución de llamada para el inflado del diseño y solo luego obtenga la posición de 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];
Utilice 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 de la raíz y luego calculo la diferencia de coordenadas con la vista.
También puede usar getLocationOnScreen()
lugar de getLocationInWindow()
.