getLocationOnScreen () vs getLocationInWindow ()

¿Cuál es la diferencia entre pantalla y vista en el contexto de estos dos métodos?

Tengo un botón y quiero obtener la coordenada x de su centro.

Supongo que esto sería suficiente

public int getButtonXPosition() { return (button.getLeft()+button.getRight())/2; } 

pero entonces, ¿qué diferencia habría si hubiera utilizado

getLocationOnScreen() o getLocationInWindow() ?

(agregando la mitad del ancho del botón a eso, por supuesto)

No creo que esta respuesta sea ​​correcta. Si creo un proyecto nuevo y edito solo MainActivity agregando el siguiente fragmento de código:

 public boolean dispatchTouchEvent(MotionEvent ev) { View contentsView = findViewById(android.R.id.content); int test1[] = new int[2]; contentsView.getLocationInWindow(test1); int test2[] = new int[2]; contentsView.getLocationOnScreen(test2); System.out.println(test1[1] + " " + test2[1]); return super.dispatchTouchEvent(ev); } 

Voy a ver impreso en la consola 108 108 . Esto es usando un Nexus 7 corriendo 4.3. Tengo resultados similares usando emuladores que ejecutan versiones de Android desde 2.2.

Las ventanas de actividad normal tendrán FILL_PARENTxFILL_PARENT como WindowManager.LayoutParams, lo que da como resultado que se extiendan al tamaño de toda la pantalla. La ventana se muestra debajo (en lo que respecta al orden z, no a las coordenadas y) de la barra de estado y otras decoraciones, por lo que creo que un gráfico más preciso sería:

 |--phone screen-----activity window---| |--------status bar-------------------| | | | | |-------------------------------------| 

Si recorre el origen de estos dos métodos, verá que getLocationInWindow atraviesa la jerarquía de vistas de su vista hasta RootViewImpl, sumndo coordenadas de vista y restando desplazamientos de desplazamiento principales. En el caso que describí anteriormente, ViewRootImpl obtiene la altura de la barra de estado de WindowSession y la pasa a través de fitSystemWindows a ActionBarOverlayLayout, que agrega este valor a la altura de la barra de acciones. ActionBarOverlayLayout toma este valor sumdo y lo aplica a su vista de contenido, que es el elemento principal de su diseño, como un margen.

Por lo tanto, su contenido se presenta más bajo que la barra de estado no como resultado de que la ventana comience en una coordenada y más baja que la barra de estado, sino que como resultado de un margen que se aplica a la vista de contenido de su actividad.

Si getLocationOnScreen en la fuente getLocationOnScreen , verás que simplemente llama a getLocationInWindow y luego agrega los coords izquierdo y superior de la ventana (que también se pasan a View by ViewRootImpl, que los obtiene de WindowSession). En el caso normal, estos valores serán ambos cero. Hay algunas situaciones en las que estos valores pueden ser distintos de cero, por ejemplo, una ventana de diálogo que se coloca en el medio de la pantalla.


Entonces, para resumir: la ventana de una actividad normal llena toda la pantalla, incluso el espacio debajo de la barra de estado y las decoraciones. Los dos métodos en cuestión devolverán las mismas coordenadas xey. Solo en casos especiales, como los diálogos en los que la ventana está realmente desplazada, estos dos valores serán diferentes.

getLocationOnScreen () obtendrá la ubicación basada en la pantalla del teléfono .

getLocationInWindow () obtendrá la ubicación en función de la ventana de actividad .

Para la actividad normal (No actividad de pantalla completa), la relación con la pantalla del teléfono y la ventana de actividad de la siguiente manera:

| – pantalla del teléfono ——————— |
| ——– barra de estado ——————— |
| |
| ——————————————- |
| ——– ventana de actividad —— ——- |
| |
| |
| |
| |
| |
| |
| ——————————————- |

Para la coordenada x, el valor de ambos métodos suele ser el mismo.

Para la coordenada y, los valores tienen una diferencia para la altura de la barra de estado

La respuesta aceptada actual es un poco prolija. Aquí hay uno más corto.

getLocationOnScreen() y getLocationInWindow() normalmente devuelven los mismos valores. Esto se debe a que la ventana normalmente tiene el mismo tamaño que la pantalla. Sin embargo, a veces la ventana es más pequeña que la pantalla. Por ejemplo, en un Dialog o un teclado de sistema personalizado.

Entonces, si sabes que las coordenadas que deseas son siempre relativas a la pantalla (como en una actividad normal), entonces puedes usar getLocationOnScreen() . Sin embargo, si su vista está en una Ventana que podría ser más pequeña que la pantalla (como en un Diálogo o teclado personalizado), entonces use getLocationInWindow() .

Relacionado

  • Cómo obtener las coordenadas