Obtener las coordenadas de View relativas al diseño de la raíz

¿Puedo obtener una posición xey de Vista en relación con el diseño raíz de mi Actividad en Android?

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.

Utilice view.getLocationOnScreen(int[] location); (ver Javadocs ). La respuesta está en la matriz de enteros (x = location[0] e y = location[1] ).

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 documento

No es necesario calcularlo manualmente.

Simplemente use getGlobalVisibleRect de esta 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(); 
 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() .

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 callback 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]; 

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; } 

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 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;