Ce qui suit est un exemple de passage des événements après avoir cliqué sur une vue.
Tout d'abord, analysez la méthode DispatchTouchEvent () dans la vue, qui est la première méthode à exécuter en cliquant sur la vue.
public boolean dispatchtouchEvent (motionEvent Event) {if (MontouchListener! = null && (mViewFlags & ENabled_mask) == ENabled && montouchListener.ontouch (this, event)) {return true; } return onTouchevent (événement);}Remarque: il contient deux fonctions de rappel ONTOUCH () et ONTOUCHEvent (); Si le contrôle est lié à l'OntouchListener et que le contrôle est activé, exécutez la méthode Ontouch (). Si la méthode renvoie vrai, cela signifie que l'événement tactile a été consommé par l'écouteur OntouchListener et ne sera pas distribué vers le bas; Mais si les faux rendements, cela signifie qu'il n'a pas été consommé et continue d'être distribué vers le bas à l'ontouchevent () du contrôle du traitement.
Analysez ensuite la méthode Ontouchevent () et effectuez un traitement supplémentaire sur les événements.
if (((ViewFlags & Clickable) == Clickable || (ViewFlags & long_clickable) == long_clicable)) {switch (event.getAction ()) {Case motionEvent.action_up: ..... PerformClick (); // répond à la pause de l'événement de clic; Case MotionEvent.Action_Down: .... Break; Case motionEvent.Action_Cancel: .... Break; Case MotionEvent.Action_Move: ..... Break; } return true; } return false;Si le contrôle est cliquable ou long_clickable, il peut répondre à l'événement correspondant et retourner vrai une fois la réponse terminée pour poursuivre la réponse. Par exemple, lorsque vous cliquez sur un événement, répondez d'abord à Action_Down, puis cassez et revenez vrai, puis relevez votre main, puis distribuez-la de DispatchTouchevent (), puis répondez à Action_up, et performClick () répondra à l'événement de clic.
Répondre aux événements de clics
public boolean performClick () {sendAccessibilityEvent (accessibilitéevent.type_view_clicked); if (monClickListener! = null) {playSoundEffECT (SoundEffecctConstants.Click); monClickListener.OnClick (this); Retour Vrai; } return false;}Exécuter monClickListener.OnClick (this); c'est-à-dire la fonction onClick () qui lie l'auditeur.
Points clés:
Comment utiliser la différence entre Ontouch et OntouchEvent?
répondre:
Lorsque le contrôle de vue reçoit un événement tactile, si le contrôle est lié à un écouteur ONTouchListener et que le contrôle est activé, exécutez la méthode ONTouch (). Si cela est vrai, l'événement tactile a été consommé et ne sera plus transmis; Si False est retourné, continuez à appeler l'événement OntouchEvent ().
Une fois que l'événement Android Touch a été transmis au décorView (un Framelayout) en haut de l'activité, il sera passé de couche par couche à travers le groupe de vue jusqu'à l'arborescence de vue, et enfin passer l'événement à la vue réelle. Voici quelques méthodes importantes.
DispatchTouchevent
Lorsqu'un événement est transmis à un groupe ViewGroup, DispatchTouchEvent sera appelé. Le code a été supprimé
public booléen DispatchTouchEvent (MotionEvent ev) {boolean manipulé = false; if (onFilterTouchEventForsecurity (ev)) {final int action = ev.getAction (); final int action masked = action & motionEvent.action_mask; // ATTENTION 1: effacer certains états lorsqu'il est enfoncé si (action masked == motionEvent.action_down) {CancelandCleartouchTargets (ev); // Notez cette méthode resettouchState (); } // Attention 2: Vérifiez si le booléen final intercepté doit être intercepté; // Si vous venez d'appuyer sur ou d'avoir une vue d'enfant pour le gérer if (ActionMasked == motionEvent.Action_Down || MFirstTouchtarget! = NULL) {final boolean DisallowIntercept = (mGroupFlags & Flag_disallow_Intercept)! = 0; if (! DisallowIntercept) {intercepted = onInterceptTouchevent (ev); ev.setAction (action); // restaurer l'action au cas où il aurait été modifié} else {intercepté = false; }} else {// Ce n'est pas le début d'une séquence d'action et il n'y a pas de sous-vue pour le gérer. Intercepté directement = true; } // L'événement n'est pas annulé et n'est pas intercepté par le groupe de vue actuel. Allez voir s'il y a une sous-vue prise en charge si (! Annuled &&! Intercepted) {// Si c'est le début d'une série d'actions ou il y a un nouveau pointeur pressé, nous devons trouver la sous-vue qui peut gérer ce pointeur si (ActionMasked. MotionEvent.action_hover_move) {final int actionIndex = ev.getActionIndex (); // Toujours 0 pour Down // La limitation ci-dessus du point de contact 32 est qu'il provoque final int idBitStoAssign = Split? 1 << ev.getPoINTERID (ActionIndex): touchtarget.all_pointer_ids; final int childRencount = mChildRencount; if (newtouchtarget == null && childRencount! = 0) {float final x = ev.getx (actionIndex); float final y = ev.gety (actionIndex); // trie tous les enfants du groupe de vue actuel et placez-le dans la couche supérieure pour commencer. ArrayList final <sewip> précommandetList = buildOrderEdChildList (); Final Boolean CustomOrder = précommandetList == null && isChildRenDrawingOrderEnabled (); Vue finale [] enfants = mchildren; pour (int i = childRencount - 1; i> = 0; i--) {final int childindex = coutumeOrder? getChildDrawingOrder (ChildCount, i): i; Vue finale child = (précommande == null)? Enfants [ChildIndex]: précommande.Get (ChildIndex); // CanViewReceivePoInterEvents Visible View peut accepter les événements // IstransFormedTouchPointInView Calcule s'il tombe sur la zone de clic si (! CanViewReceivePointevents (Child) ||! IstransformedTouchPpointFocus (x, y, enfant, null)) {ev.setTargetAccessibilityFocus (false); continuer; } // peut gérer si la vue de ce pointeur a traité le pointeur précédent, puis utiliser newtouchtarget = getTouchtarget (enfant); if (newtouchtarget! = null) {// L'enfant reçoit déjà le toucher dans ses limites. // Donnez-lui le nouveau pointeur en plus de ceux qu'il manipule. newtouchtarget.poINTERIDBITS | = idbitStoassign; casser; }} // Attention 3: Envoyez-le directement à la vue de l'enfant if (DispatchTransformEdTouchevent (EV, FALSE, Child, idbitStoAssign)) {// Child veut recevoir le toucher dans ses limites. mlastTouchdowntime = ev.getDowntime (); if (précommandedList! = null) {// ChildIndex pointe dans la liste prévenue, trouvez l'index d'origine pour (int j = 0; j <childrencount; j ++) {if (enfants [childindex] == mchildren [j]) {mlastTouchDownIndex = j; casser; }}} else {mlastTouchDownIndex = childIndex; } mlastTouchdown = ev.getx (); mlastTouchDowny = ev.gety (); newtouchtarget = addtouchtarget (enfant, idbitStoassign); déjàDispatchedToneWtouchTarget = true; casser; }}}}}} // La vue d'enfant recevant l'événement a déjà été trouvée. S'il est nul, cela signifie qu'aucune vue d'enfant n'est prise en charge. Le ViewGroup actuel doit gérer if (mFirstTouchtarget == null) {// ViewGroup manreilled = DispatchTransformEdTouchevent (EV, CancelChild, Null, TouchTarget.All_PoINTER_IDS); } else {if (déjàDispatchEdToneWtouchtarget) {// ignore un code if (DispatchTransformEdTouchevent (ev, CancelChild, Target.Child, Target.PoINTERIDBITS)) {Manipted = true; }}} retour géré;}L'attention dans le code ci-dessus sera impliquée dans la dernière partie, alors faites attention à lui.
Il convient de souligner ici que différents pointeurs d'une série d'actions peuvent être attribués à différentes vues pour répondre. ViewGroup conservera un pointer et une liste de tactiles qui gèrent les vues. Un touchet de touche représente une sous-vue qui peut gérer les pointeurs. Bien sûr, une vue peut gérer plusieurs pointeurs, comme les deux doigts se trouvent dans une zone de sous-vue. TouchTarget utilise un en interne pour stocker le pointer qu'il peut traiter et un bits INT32, c'est pourquoi la couche supérieure ne peut permettre que jusqu'à 32 points de contact en même temps.
Examinons le code à l'attention 3. Nous disons souvent que si le DispatchTouchEvent de la vue revient faux, il ne peut pas être suivi de l'action. Pourquoi est-ce? Parce que si FALSE est renvoyé à l'attention 3, il ne sera pas enregistré dans le touchtarget, ViewGroup pense que vous n'avez pas la possibilité de gérer cet événement.
Vous pouvez voir ici que ViewGroup gère vraiment les événements dans DispatchTransformEdTouchevent, suivez et jetez un œil:
DispatchTransformedTouchEventPrivate Boolean DispatchTransformEdTouchevent (MotionEvent Event, booléen Annuler, View Child, int deeredPoInterIdBits) {// pas de traitement de sous-classe, puis laisse-le à la vue View pour le traitement if (child == null) {manipulé = super.DispatchToucheventivent (transformEvent); } else {float final offsetx = mscrollx - child.mleft; Offsey float final = mscrolly - child.mtop; transformEvent.offsetLocation (Offsetx, Offsety); if (! child.hasIdentityMatrix ()) {transformEvent.transform (child.getInversEMatrix ()); } manipulé = child.dispatchTouchEvent (transformEvent); } retour géré;}Vous pouvez voir que quoi qu'il arrive, le dépôt de la vue sera appelé, c'est là que l'événement de clic est vraiment géré.
DispatchTouchEvent Boolean DispatchTouchevent (MotionEvent Event) {if (onFilterTouchEventForSecurity (événement)) {// Obtenez l'événement ONTOUCH de la vue d'abord, si Ontouch renvoie le vrai écouteur LI = MLISTEDERINFO; if (li! = null && li.montouchListener! = null && (mViewFlags & eveloable_mask) == ENTIPED && li.montouchListener.ontouch (this, event)) {result = true; } if (! result && onTouchEvent (événement)) {result = true; }} Retour Résultat; }L'événement Ontouch que nous avons défini pour la vue est à une priorité plus élevée. Si l'exécution d'Ontouch renvoie vrai, alors l'OntouchEvent de la vue n'ira pas à la vue. Certains de nos événements de clic sont gérés dans le OnTouchevent, c'est pourquoi l'Ontouch renvoie true, et les événements liés au clic de la vue ne seront pas traités.
Un bref résumé de ce processus
Lorsque ViewGroup accepte les événements transmis par les supérieurs, s'il s'agit du début d'une série d'événements tactiles (Action_Down), ViewGroup vérifie d'abord s'il doit intercepter l'événement (sur InterceptTouchevent, l'implémentation par défaut de ViewGroup renvoie directement False pour indiquer qu'il n'intercepte pas), puis ViewGroup Traverse toutes ses opinions. Trouvez la vue que vous cliquez actuellement et appelez immédiatement le DispatchTouchEvent de la vue cible. Si le DispatchTouchEvent de la vue cible renvoie faux, il pense que la vue cible n'est que dans cette position. Il ne veut pas accepter cet événement, mais veut juste faire une vue tranquillement (je vous regarde tranquillement faire semblant *). À l'heure actuelle, ViewGroup ira également au DispatchTouchEvent, fait!