2011-12-09 15 views
13

Tengo una imagen que estoy mostrando a un usuario en mi aplicación de Android.Obtener coordenadas táctiles relativas a una vista (equivalente a ScreenToClient)

Quiero ser capaz de decir dónde 'tocan' la imagen.

puedo conseguir fácilmente la pantalla de coordenadas mediante la implementación de un OnTouchListener

private OnTouchListener image_Listener = new OnTouchListener(){ 
    @Override 
    public boolean onTouch(View v, MotionEvent event) { 
     if(event.getAction() == MotionEvent.ACTION_UP) { 
      float x = event.getX(); 
      float y = event.getY(); 
      return true; 
     } 
     return false; 
    } 
}; 

Sin embargo, estos son coordenadas absolutas. Lo que realmente necesito es una función para convertir esto en coordenadas relativas a una Vista ...

He hecho un poco de investigación, pero parece que no puedo encontrar nada, aparte de mí tratando de implementar un método ScreenToClient yo mismo ..

¿Alguien sabe de una buena solución para esto, o voy a tener que hacer mi propia?

Parece que el tipo de método estaría disponible, es por eso que estoy preguntando.

Gracias a todos por su tiempo.

EDITAR: No estoy tan seguro de que las coordenadas ya no sean relativas a la vista. Podría haber jurado leer que las coordenadas eran absolutas, pero después de algunos retoques, tengo las cosas funcionando como esperaba ... Perdón por el ruido chicos.

Respuesta

20

Solo para responder, los toques son relativos a la vista en cierto modo. Sí, son coordenadas de pantalla sin formato del tacto. Sin embargo, dado que registra el evento táctil en la vista en sí, solo se activará si el usuario realmente toca la vista. Eso significa que, aunque las coordenadas de la pantalla son coordenadas de pantalla en bruto, están dentro de los límites de la vista.

Si desea obtener las coordenadas X/Y de la vista tocado en relación a sólo a sí mismo, entonces se puede subract la izquierda coordinar con la pantalla de coordenadas y la parte superior de coordenadas de la coordenada y de este modo:

private OnTouchListener image_Listener = new OnTouchListener(){ 
    @Override 
    public boolean onTouch(View v, MotionEvent event) { 
     if(event.getAction() == MotionEvent.ACTION_UP) { 
      float screenX = event.getX(); 
      float screenY = event.getY(); 
      float viewX = screenX - v.getLeft(); 
      float viewY = screenY - v.getTop(); 
      return true; 
     } 
     return false; 
    } 
}; 

Con eso, si el usuario tocó 40 x-píxeles en la pantalla, pero el margen izquierdo se estableció en 10, entonces viewX sería 30. Si movió la vista hacia abajo 40 x-pixels y el usuario tocó el mismo punto en la vista, todavía sería 30.

Se vuelve un poco más complicado si incluiste el relleno como relleno dentro de una Vista todavía cuenta como una Vista a pesar de que no muestra nada.

EDIT:

Debo señalar que lo que Pedro dijo es verdad. Si toca una vista, continuará recibiendo eventos táctiles hasta que se levante el dedo, incluso si arrastra el dedo fuera de los límites de la vista. Esto significa que ACTION_UP puede recibir coordenadas táctiles para su vista que no están dentro de los límites.

+0

Gracias por su respuesta. – syllogism

+0

Estoy llegando la misma pregunta. Desde el tutorial, estos métodos, como view.getLeft(). "devolver la ubicación de la vista relativa a su padre". A menudo, con un diseño complicado, la vista investigada no es un elemento directo de una vista de pantalla. Entonces el método mencionado por Deev no puede aplicarse siempre. Alguna idea nueva? – user1914692

+4

Hmm, encuentro una forma: use View.getLocationOnScreen() y/u getLocationInWindow(). – user1914692

2

Las coordenadas del evento táctil son relativas a la vista que recibe el evento. Sin embargo, no están limitados al tamaño de la Vista, ya que el usuario puede obviamente deslizarse fuera de la vista con el mismo movimiento.

Hasta que se active ACTION_UP o ACTION_CANCEL, la vista continuará recibiendo los eventos de movimiento incluso si el puntero está fuera de la vista.

¿Estás seguro de que el oyente está registrado en la vista correcta?

+0

Sí, me inscribí a la vista derecha .. Tengo cosas que trabajan como yo esperaba. Simplemente estaba haciendo las cosas más difíciles de lo que necesitaban. Gracias por su respuesta. – syllogism

18

Acabo de tener el mismo problema, y ​​al probar la solución DeeV siempre recibí 0 de los métodos getLeft() y getTop(). Como cambiar el diseño no era una opción (porque creo que getTop/Left es relativo solo al padre de la vista) tuve que descubrir cómo obtener la posición absoluta de la vista.

Aquí es un enfoque similar utilizando getLocationOnScreen (ubicación):

protected Point getRelativePosition(View v, MotionEvent event) { 
    int[] location = new int[2]; 
    v.getLocationOnScreen(location); 
    float screenX = event.getRawX(); 
    float screenY = event.getRawY(); 
    float viewX = screenX - location[0]; 
    float viewY = screenY - location[1]; 
    return new Point((int) viewX, (int) viewY); 
} 
+0

Éste funciona, mientras que 'screenY - v.getTop()' no (al menos para mí) – 18446744073709551615

+0

v.getTop() tampoco funcionaba para mí. Alguien tiene alguna idea de por qué? – eliasbagley

+0

@eliasbagley: v.getTop() es relativo al padre de v mientras que screenY es relativo a la pantalla. Solo funciona si el padre va a la parte superior de la pantalla. – user362178

Cuestiones relacionadas