2011-09-16 10 views
17

No estoy preguntando cómo manejar eventos táctiles, pero ¿qué está sucediendo detrás de escena? Si hay varios widgets anidados, ¿en qué orden ven los eventos? ¿El desarrollador tiene algún control sobre eso? Idealmente, me gustaría un documento sobre el tema.¿Cómo se envían los eventos de Android touch?

Respuesta

21

Desde el punto de vista de la actividad:

eventos táctiles se entregan primero en Activity.dispatchTouchEvent. Es donde puedes atraparlos primero.

Aquí se envían a la ventana, donde atraviesan la jerarquía de vistas, de manera que los widgets que se dibujan al final (sobre otros widgets) tienen la oportunidad de procesarlos en View.onTouchEvent primero. Si alguna Vista devuelve verdadero en onTouchEvent, el recorrido se detiene y otras Vistas no reciben evento táctil.

Finalmente, si ninguna Vista consume el toque, se envía a Activity.onTouchEvent.

Eso es todo su control. Y es lógico que lo que ves dibujado sobre otra cosa, tenga la oportunidad de procesar el evento táctil antes que algo dibujado debajo de él.

+0

¿Tiene algún tipo de documento que describe esto? – DJClayworth

+0

Acerca del envío: Puedo leer el código fuente y los comentarios de la función. Acerca del orden de vista transversal: lo he leído en algún documento, sin duda en developer.android.com, pero no puedo decir exactamente ahora. –

+0

De todos modos, buen comienzo: http://developer.android.com/guide/topics/ui/ui-events.html –

10

Echemos un vistazo a un ejemplo visual.

enter image description here

Cuando se produce un evento de contacto, en primer lugar a todos es notificado del evento, a partir de la actividad y va hasta el final a la vista en la parte superior. Luego, todos tienen la oportunidad de manejar el evento, comenzando con la vista en la parte superior y volviendo a la actividad. Entonces, la Actividad es la primera en enterarse y la última en tener la oportunidad de manejarlo.

enter image description here

si la actividad o algún ViewGroup quiere manejar el evento táctil de inmediato (y no le dan al otro por la línea de la oportunidad en ello) entonces, sólo se puede volver true en su onInterceptTouchEvent().

Si una vista (o un grupo de visualización) tiene un OnTouchListener, el evento táctil se maneja con OnTouchListener.onTouch(). De lo contrario, es manejado por onTouchEvent(). Si onTouchEvent() devuelve true para cualquier evento táctil, el manejo se detiene allí. Nadie más en el futuro tiene la oportunidad de hacerlo.

explicación más detallada

El diagrama anterior hace las cosas un poco más sencillo de lo que realmente son. Por ejemplo, entre la actividad y el grupo de visualización A (el diseño raíz) también están la ventana y el decorado. Los dejé arriba porque generalmente no tenemos que interactuar con ellos. Sin embargo, los incluiré a continuación. La siguiente descripción sigue un evento táctil a través del código fuente. Puede hacer clic en un enlace para ver el código fuente real.

  1. La actividad de dispatchTouchEvent() se notifica de un evento táctil. El evento táctil se transfiere como MotionEvent, que contiene las coordenadas x, y, la hora, el tipo de evento y otra información.
  2. El evento táctil se envía al superDispatchTouchEvent() de la ventana. Window es una clase abstracta. La implementación real es PhoneWindow.
  3. El siguiente en la fila para recibir la notificación es DecorView's superDispatchTouchEvent().DecorView es lo que maneja la barra de estado, la barra de navegación, el área de contenido, etc. It is actually just a FrameLayout subclass, que a su vez es una subclase de ViewGroup.
  4. El siguiente para recibir la notificación (corríjame si me equivoco) es la vista de contenido de tu actividad. Eso es lo que establece como el diseño raíz de su actividad en xml cuando crea el diseño en el Editor de diseño de Android Studio. Entonces, ya sea que elija RelativeLayout, LinearLayout o ConstraintLayout, todas son subclases de ViewGroup. Y ViewGroup recibe una notificación del evento táctil en dispatchTouchEvent(). Este es el ViewGroup A en mis diagramas arriba.
  5. ViewGroupnotify any children tiene el evento táctil, incluyendo cualquier ViewGroup niños. Esto es ViewGroup B en mis diagramas arriba.
  6. En cualquier parte del camino, un ViewGroup puede short-circuit el proceso de notificación devolviendo true para onInterceptTouchEvent().
  7. Suponiendo que no ViewGroup corta las notificaciones, el final natural de la línea para las notificaciones es cuando se llama a la vista dispatchTouchEvent().
  8. Ahora es el momento para comenzar a manejar los eventos. If there is an OnTouchListener, entonces tiene la primera oportunidad de manejar el evento táctil con onTouch(). Otherwise, la Vista onTouchEvent() se encarga de manejarlo.
  9. Ahora todos los ViewGroups recursivamente arriba de la línea tienen la oportunidad de manejar el evento táctil de la misma manera que lo hizo View. Aunque, no indicarlo en el diagrama anterior, un ViewGroup es una subclase View, así que todo lo descrito acerca OnTouchListener.onTouch() y onTouchEvent() también se aplica a ViewGroups.
  10. Finally, si nadie más lo quería, la actividad también tiene la última oportunidad para controlar el evento con onTouchEvent().

FAQ

Cuándo alguna vez necesitará anular dispatchTouchEvent()?

Probablemente no sea necesario, a menos que necesite hacer un enrutamiento adicional que no ocurre de forma predeterminada. Para supervisar las notificaciones de eventos táctiles, puede anular onInterceptTouchEvent().

¿Cuándo tendría que anular alguna vez onInterceptTouchEvent()?

Si solo quiere espiar las notificaciones táctiles que están entrando, puede hacerlo aquí y devolver false.

Sin embargo, el principal propósito de anular este método es dejar que el ViewGroup manejar un determinado tipo de evento táctil mientras que dejan el niño a manejar otro tipo. Por ejemplo, un ScrollView hace esto para manejar el desplazamiento mientras deja que su hijo maneje algo así como un clic de botón. Por el contrario, si la vista secundaria no quiere que su padre robe su evento táctil, puede llamar al requestDisallowTouchIntercept().

¿Cuáles son los tipos de eventos táctiles?

Los principales son

  • ACTION_DOWN - Este es el comienzo de un evento de toque. Siempre debe devolver true para el evento ACTION_DOWN en onTouchEvent si desea manejar un evento táctil. De lo contrario, no recibirá más eventos entregados a usted.
  • ACTION_MOVE - Este evento se dispara continuamente a medida que mueve el dedo por la pantalla.
  • ACTION_UP - Este es el último evento de un evento táctil.

Un finalista es ACTION_CANCEL. Se llama a esto si un ViewGroup en el árbol decide interceptar el evento táctil.

Puede ver los otros tipos de MotionEvents here. Dado que Android es multitáctil, los eventos también se disparan cuando otros dedos ("punteros") tocan la pantalla.

estudio adicional

Cuestiones relacionadas