Estoy tratando de obtener las coordenadas absolutas de píxeles de la pantalla de la esquina superior izquierda de una vista. Sin embargo, todos los métodos que puedo encontrar como getLeft()
y getRight()
no funcionan, ya que todos parecen ser relativos al padre de la vista, lo que me da 0
. ¿Cuál es la forma apropiada de hacer esto?
Si ayuda, esto es para un juego de "poner la imagen de nuevo en orden". Quiero que el usuario pueda dibujar un cuadro para seleccionar varias piezas. Mi suposición es que la forma más fácil de hacerlo es hacia getRawX()
y getRawY()
desde el MotionEvent
y luego comparar esos valores con la esquina superior izquierda del diseño que contiene las piezas. Conociendo el tamaño de las piezas, puedo determinar cuántas piezas se han seleccionado. Me doy cuenta de que puedo usar getX()
y getY()
en el MotionEvent
, pero como eso devuelve una posición relativa que hace que determinar qué piezas fueron seleccionadas sea más difícil. (No es imposible, lo sé, pero parece innecesariamente complicado).
Editar: este es el código que usé para tratar de obtener el tamaño del contenedor de retención, según una de las preguntas. TableLayout
es la mesa que contiene todas las piezas del rompecabezas.
TableLayout tableLayout = (TableLayout) findViewById(R.id.tableLayout);
Log.d(LOG_TAG, "Values " + tableLayout.getTop() + tableLayout.getLeft());
Edición 2: Aquí está el código que he probado, siguiendo más de las respuestas sugeridas.
public int[] tableLayoutCorners = new int[2];
(...)
TableLayout tableLayout = (TableLayout) findViewById(R.id.tableLayout);
tableLayout.requestLayout();
Rect corners = new Rect();
tableLayout.getLocalVisibleRect(corners);
Log.d(LOG_TAG, "Top left " + corners.top + ", " + corners.left + ", " + corners.right
+ ", " + corners.bottom);
cells[4].getLocationOnScreen(tableLayoutCorners);
Log.d(LOG_TAG, "Values " + tableLayoutCorners[0] + ", " + tableLayoutCorners[1]);
Este código se agregó después de completar toda la inicialización. La imagen se ha dividido en una matriz de ImageViews (la matriz de celdas []) contenida dentro de a TableLayout
. Las celdas [0] están en la parte superior izquierda ImageView
, y elegí las celdas [4] ya que está en algún lugar en el medio y definitivamente no debería tener coordenadas de (0,0).
El código que se muestra arriba todavía me da todos los 0 en los registros, lo que realmente no entiendo porque las diversas piezas del rompecabezas se muestran correctamente. (Intenté public int para tableLayoutCorners y la visibilidad predeterminada, ambos dieron el mismo resultado).
No sé si esto es significativo, pero los ImageView
s originalmente no tienen un tamaño. El tamaño de los ImageView
s se determina durante la inicialización automáticamente por la Vista cuando le doy una imagen para mostrar. ¿Podría esto contribuir a que sus valores sean 0, a pesar de que el código de registro es después de que se les haya dado una imagen y se hayan redimensionado automáticamente? Para contrarrestar eso, agregué el código tableLayout.requestLayout()
como se muestra arriba, pero eso no ayudó.
fuente
La respuesta aceptada en realidad no decía cómo obtener la ubicación, así que aquí hay un poco más de detalle. Se pasa una
int
matriz de longitud 2 y los valores se reemplazan con las coordenadas de la vista (x, y) (de la esquina superior izquierda).Notas
getLocationOnScreen
congetLocationInWindow
debería dar los mismos resultados en la mayoría de los casos (ver esta respuesta ). Sin embargo, si se encuentra en una ventana más pequeña, como un cuadro de diálogo o un teclado personalizado, entonces deberá elegir cuál se adapta mejor a sus necesidades.(0,0)
si llama a este métodoonCreate
porque la vista aún no se ha presentado. Puede usar aViewTreeObserver
para escuchar cuándo se realiza el diseño y puede obtener las coordenadas medidas. (Ver esta respuesta )fuente
Primero debes obtener el rectángulo visible local de la vista
Por ejemplo:
Espero que esto ayude
fuente
getGlobalVisibleRect()
para coordenadas absolutas.Usar un oyente de diseño global siempre me ha funcionado bien. Tiene la ventaja de poder volver a medir las cosas si se cambia el diseño, por ejemplo, si algo se establece en View.GONE o se agregan / eliminan vistas secundarias.
fuente
setContentView()
causó un problema en un especialActivity
en mi aplicación! Esa fue una actividad de diálogo (windowFrame:@null, windowActionBar:false, windowIsFloating:true, windowNoTitle:true
). Su diseño principal (aLinearLayout
) no tiene ningún hijo directo con determinadolayout_width
(Todos ellos fueronmatch_parent
owrap_content
).Siguiendo el comentario de Romain Guy, así es como lo arreglé. Esperemos que ayude a cualquiera que también haya tenido este problema.
De hecho, estaba tratando de obtener las posiciones de las vistas antes de que se presentaran en la pantalla, pero no era del todo obvio que sucediera. Esas líneas se colocaron después de que se ejecutó el código de inicialización, por lo que supuse que todo estaba listo. Sin embargo, este código todavía estaba en onCreate (); Al experimentar con Thread.sleep () descubrí que el diseño no está realmente finalizado hasta después de que onCreate () hasta que onResume () haya terminado de ejecutarse. De hecho, el código estaba tratando de ejecutarse antes de que el diseño terminara de colocarse en la pantalla. Al agregar el código a un OnClickListener (o algún otro Listener) se obtuvieron los valores correctos porque solo se podía disparar una vez que el diseño había terminado.
La línea a continuación se sugirió como edición comunitaria:
por favor use
onWindowfocuschanged(boolean hasFocus)
fuente
setContentView(R.layout.something)
, pero no se han cargado visualmente. No tienen un tamaño o una posición. Eso no sucede hasta que finaliza la primera pasada de diseño, lo que sucede en algún momento en el futuro (generalmente después de onResume ()).Primera forma:
En Kotlin podemos crear una extensión simple para ver:
Y simplemente obtenga coordenadas:
Segunda forma:
La segunda forma es más simple:
y simplemente obtener X absoluto por
view.absX()
Y porview.absY()
fuente
val location = IntArray(2).apply(::getLocationOnScreen)
Mis utilidades funcionan para obtener la ubicación de la vista, devolverá un
Point
objeto conx value
yy value
Utilizando
fuente
Puede obtener las coordenadas de una vista usando
getLocationOnScreen()
ogetLocationInWindow()
Luego,
x
yy
debe ser la esquina superior izquierda de la vista. Si su diseño raíz es más pequeño que la pantalla (como en un Diálogo), el usogetLocationInWindow
será relativo a su contenedor, no a toda la pantalla.Solución Java
Para garantizar que la vista haya tenido la oportunidad de actualizarse, ejecute su solicitud de ubicación después de que se haya calculado el nuevo diseño de la Vista utilizando
view.post
:~~
Solución Kotlin
Para garantizar que la vista haya tenido la oportunidad de actualizarse, ejecute su solicitud de ubicación después de que se haya calculado el nuevo diseño de la Vista utilizando
view.post
:Recomiendo crear una función de extensión para manejar esto:
Y si necesita confiabilidad, agregue también:
fuente
Use este código para encontrar las coordenadas exactas de X e Y:
He agregado / restado algunos valores para ajustar mi vista. Haga estas líneas solo después de que se haya inflado toda la vista.
fuente
Obtenga tanto la posición de visualización como la dimensión en la pantalla
fuente
Además de las respuestas anteriores, para la pregunta ¿dónde y cuándo debe llamar
getLocationOnScreen
?En cualquier información relacionada con cualquier vista que desee obtener, solo estará disponible después de que la vista se haya presentado en la pantalla. Puede hacer esto fácilmente poniendo su código que depende de la creación de la vista dentro de este (view.post (Runnable)):
fuente