El siguiente es un ejemplo de evento de evento después de hacer clic en una vista.
Primero, analice el método DispatkTouchEvent () en la vista, que es el primer método para ejecutar haciendo clic en la vista.
Public boolean DispatchTouchEvent (evento MotionEvent) {if (MonTouchListener! = NULL && (mviewFlags & Endabled_Mask) == endabled && monTouchListener.onTouch (this, event)) {return true; } return onTouchEvent (evento);}NOTA: Contiene dos funciones de devolución de llamada OnTouch () y OnTouchEvent (); Si el control está vinculado al OnTouchListener y el control está habilitado, ejecute el método OnTouch (). Si el método devuelve verdadero, significa que el evento táctil ha sido consumido por el oyente de OnTouchListener y no se distribuirá hacia abajo; Pero si los falsos retornan, significa que no se ha consumido y continúa distribuyendo hacia abajo al OnTouchEvent () del control para el procesamiento.
Luego analice el método OnTouchEvent () y realice un mayor procesamiento de eventos táctiles.
if ((((ViewFlags & Clickable) == Clickable || (ViewFlags & Long_Clickable) == Long_Clickable)) {switch (event.getAction ()) {case MotionEvent.Action_Up: .....informClick (); // Responder a hacer clic en la ruptura del evento; caso MotionEvent.Action_down: .... ruptura; caso MotionEvent.Action_Cancel: .... break; caso MotionEvent.Action_move: ..... Break; } return verdadero; } return false;Si el control se puede hacer clic o Long_clickable, puede responder al evento correspondiente y devolver verdadero después de que se complete la respuesta para continuar la respuesta. Por ejemplo, al hacer clic en un evento, primero responda a Action_Down, luego rompa y devuelva verdadero, luego levante la mano, luego distribuya desde DispatchTouchEvent () y luego responda a Action_Up, y ScoreClick () responderá al evento de clic.
Responder a los eventos de clics
public boolean ScneClick () {sendAccessibilityEvent (accesibilidadeVent.type_view_clicked); if (MonClickListener! = NULL) {PlaySoundEffect (SoundEffectConstants.click); MonClickListener.onclick (esto); devolver verdadero; } return false;}Ejecutar MonClickListener.Onclick (esto); Es decir, la función OnClick () que une al oyente.
Puntos clave:
¿Cómo usar la diferencia entre OnTouch y OnTouchEvent?
respuesta:
Cuando el control de la vista recibe un evento táctil, si el control está vinculado a un oyente de OnTouchListener y el control se habilita, ejecute el método OnTouch (). Si es cierto, el evento táctil se ha consumido y ya no se transmitirá; Si se devuelve False, continúe llamando al evento OnTouchEvent ().
Una vez que el evento de Android Touch pase a DecorView (un Framelayout) en la parte superior de la actividad, se pasará capa por capa a través del grupo de vista al árbol View, y finalmente pasará el evento a la vista recibida real. Aquí hay algunos métodos importantes.
DispatchTouchEvent
Cuando se pasa un evento a un grupo de visualización, se llamará a DispatchTouchEvent. El código ha sido eliminado
Public boolean DispatchTouchEvent (MotionEvent EV) {boolean manejado = falso; if (onFilterTouchEventForSecurity (EV)) {final int action = ev.getAction (); Final int ActionMasked = Action & MotionEvent.Action_MASK; // Atención 1: Borre algunos estados cuando se presione si (ActionMasked == MotionEvent.Action_Down) {CancelAndClArTouchTargets (EV); // Tenga en cuenta este método ResettouchState (); } // Atención 2: Compruebe si el booleano final es necesario interceptarse; // Si solo presionó o tiene una vista infantil para manejarlo si (ActionMasked == MotionEvent.Action_Down || MfirstTouchTarget! = NULL) {final Boolean desescribeintercept = (mgroupflags & flag_disallow_intercept)! = 0; if (! deseshowintercept) {intercepted = oninterceptTouchEvent (ev); ev.SetAction (acción); // Restaurar acción en caso de que se haya cambiado} else {interceptado = false; }} else {// No es el comienzo de una secuencia de acción y no hay una subvisión para manejarlo. Interceptado directamente = verdadero; } // El evento no se cancela y no es interceptado por el Grupo de vista actual. Vaya a ver si hay una subvisión tomada if (! Canceled &&! Intercepted) {// Si este es el comienzo de una serie de acciones o si hay un nuevo puntero presionado, necesitamos encontrar la subvención que puede manejar este puntero si (ActionMasked == MotionEvent.Action_down || (Action && ActionMasked == Motion.Action_PoNinter) MotionEvent.action_hover_move) {final int actionIndex = ev.getActionIndex (); // siempre 0 para hacia abajo // La limitación anterior del punto de contacto 32 es que causa int idbitstoassign final = dividir? 1 << ev.getpointerid (ActionIndex): touchTarget.all_pointer_ids; Final int Childrencount = MCHIRDRENCENT; if (newTouchTarget == NULL && ChildRencount! = 0) {Final Float x = ev.getx (ActionIndex); Flotador final y = ev.gety (ActionIndex); // Ordene todas las vistas infantiles del grupo de vista actual y colóquelas en la capa superior para comenzar. Final ArrayList <Iriew> PreorderedList = buildOrderedChildList (); Final Boolean CustomOrder = PreorderedList == null && ischildrendrawingerDloDENSABLED (); Vista final [] Niños = McHildren; para (int i = childRencount-1; i> = 0; i--) {final int childIndex = CustomOrder? GetChildDrawingOrder (ChildCount, I): I; Vista final Child = (PreorderedList == NULL)? niños [ChildIndex]: PreorderedList.get (ChildIndex); // CanviewReceivePointerevents Visible View puede aceptar eventos // istransformedTouchPointInview Calcule si cae en el área de clic if (! CanviewReceivePointerevents (child) || continuar; } // puede manejar si la vista de este puntero ha procesado el puntero anterior, luego usar newTouchTarget = getTouchTarget (niño); if (newTouchTarget! = NULL) {// El niño ya está recibiendo toque dentro de sus límites. // Déle el nuevo puntero además de los que maneja. newTouchTarget.pointerIdBits | = IdBitStoAssign; romper; }} // Atención 3: Envíelo directamente a la vista del niño if (DispatchTransformedTouchEvent (EV, False, Child, IdBitStoAssign)) {// El niño quiere recibir toque dentro de sus límites. mlastTouchDowntime = ev.getDowntime (); if (PreorderedList! = NULL) {// ChildIndex señala en una lista previa, encuentre el índice original para (int j = 0; j <childRencount; j ++) {if (children [childIndex] == mChildren [j]) {mlastTouchdownIndex = j; romper; }}} else {mlastTouchdownIndex = ChildIndex; } mlastTouchDownx = ev.getx (); mlastTouchDowny = ev.gety (); newTouchTarget = addTouchTarget (Child, IdBitStoAssign); yaDisPatchedToneWTouchTarget = true; romper; }}}}}} // La vista del niño que recibe el evento se ha encontrado antes. Si es nulo, significa que no se hace cargo ninguna vista del niño. El grupo de vista actual debe manejar if (mfirstTouchTarget == null) {// ViewGroup Handled = DispatchTransformedTouchEvent (EV, CancelChild, Null, TouchTarget.all_pointer_ids); } else {if (yaDisPatchedToneWTouchTarget) {// Ignorar algún código if (DispatchTransformedTouchEvent (ev, cancelchild, target.child, target.pointerIdBits)) {Handled = true; }}} return manejado;}La atención en el código anterior estará involucrado en la parte posterior, así que preste atención.
Debe señalarse aquí que se pueden asignar diferentes punteros en una serie de acciones a diferentes puntos de vista para responder. ViewGroup mantendrá un puntero y una lista de TouchTargets que manejan vistas. Un TouchTarget representa una subvisión que puede manejar punteros. Por supuesto, una vista puede manejar múltiples punteros, como ambos dedos están en un área de subvisión. TouchTarget utiliza un int internamente para almacenar el puntero que puede procesar y un int32 bits, por lo que la capa superior solo puede permitir hasta 32 puntos de tacto al mismo tiempo.
Veamos el código a la atención 3. A menudo decimos que si el tiempo de desplazamiento de la vista devuelve falso, entonces la acción no puede seguir. ¿Por qué es esto? Porque si False se devuelve a la atención 3, entonces no se registrará en TouchTarget, ViewGroup cree que no tiene la capacidad de manejar este evento.
Puede ver aquí que ViewGroup realmente maneja los eventos en DispathTransformedTouchEvent, siga y eche un vistazo:
DispatchTransformedTouchEventPrivate boolean DispatchTransformedTouchEvent (evento de MotionEvent, cancelación booleana, Ver Child, int desireedPointerIdBits) {// sin procesamiento de subclase, luego deje que se vea al grupo de vista para procesar si (child == null) {handled = super.dispatchTouchEvent (transformedEvent); } else {Final Float offsetX = mscrollx - child.mleft; Flotador final Offsety = mscrolly - child.mtop; transformedEvent.OffSetLocation (offSetX, offSety); if (! child.hasidentitymatrix ()) {transformedEvent.Transform (child.getInverSematrix ()); } manejado = child.dispatchTouchEvent (transformedEvent); } retorno manejado;}Puede ver que pase lo que pase, se llamará a la vista de la vista, que es donde realmente se maneja el evento de clic.
DispatkTouchEvent public boolean DispatchTouchEvent (evento MotionEvent) {if (OnFilterTouchEventForSecurity (Event)) {// Obtenga el evento OnTouch de la vista primero, si OnTouch devuelve verdadero ListenInfo li = mListenerInfo; if (li! = null && li.monTouchListener! = null && (mviewFlags & Endably_mask) == Enhabled && li.monTouchListener.onTouch (this, event)) {result = true; } if (! resultado && onTouchEvent (evento)) {resultado = true; }} Resultado de retorno; }El evento OnTouch que establecemos para la vista es de mayor prioridad. Si la ejecución de OnTouch devuelve verdadera, entonces el intouchevent de la vista no irá a la vista. Algunos de nuestros eventos de clics se manejan en OnTouchEvent, por lo que el OnTouch devuelve verdadero, y los eventos relacionados con el clic de la vista no se procesarán.
Un breve resumen de este proceso
Cuando ViewGroup acepta los eventos transmitidos por los superiores, si es el comienzo de una serie de eventos táctiles (Action_Down), ViewGroup primero verificará si necesita interceptar el evento (OnInterceptTouchEvent, la implementación predeterminada de ViewGroup devuelve directamente falso para indicar que no intercepta), y luego ViewGroup atraviesa todas sus opiniones. Encuentre la vista en la que está haciendo clic actualmente e inmediatamente llame al Touchevent de la vista de destino. Si el TouchEvent de la vista de destino devuelve falso, entonces cree que la vista de destino está solo en esa posición. No quiere aceptar este evento, pero solo quiere hacer una vista en silencio (en silencio te veo fingir*). En este momento, ViewGroup también irá al DispatchTouchEvent, ¡listo!