Le meilleur endroit pour démystifier cela est le code source. Les documents sont terriblement insuffisants pour expliquer cela.
dispatchTouchEvent est en fait défini sur Activity, View et ViewGroup. Considérez-le comme un contrôleur qui décide comment acheminer les événements tactiles.
Par exemple, le cas le plus simple est celui de View.dispatchTouchEvent qui acheminera l'événement tactile vers OnTouchListener.onTouch s'il est défini ou vers la méthode d'extension onTouchEvent .
Pour ViewGroup.dispatchTouchEvent, les choses sont beaucoup plus compliquées. Il doit déterminer laquelle de ses vues enfant doit obtenir l'événement (en appelant child.dispatchTouchEvent). Il s'agit essentiellement d'un algorithme de test de réussite dans lequel vous déterminez quel rectangle de délimitation de la vue enfant contient les coordonnées du point de contact.
Mais avant de pouvoir envoyer l'événement à la vue enfant appropriée, le parent peut espionner et / ou intercepter l'événement tous ensemble. C'est pourquoi onInterceptTouchEvent est là. Donc, il appelle cette méthode avant de faire le test de hit et si l'événement a été détourné (en renvoyant true depuis onInterceptTouchEvent), il envoie un ACTION_CANCEL aux vues enfant afin qu'ils puissent abandonner leur traitement des événements tactiles (des événements tactiles précédents) et à partir de là. tous les événements tactiles au niveau parent sont envoyés à onTouchListener.onTouch (si défini) ou onTouchEvent (). Dans ce cas également, onInterceptTouchEvent n'est plus appelé.
Souhaitez-vous même remplacer [Activity | ViewGroup | View] .dispatchTouchEvent? À moins que vous ne fassiez un routage personnalisé, vous ne devriez probablement pas le faire.
Les principales méthodes d'extension sont ViewGroup.onInterceptTouchEvent si vous souhaitez espionner et / ou intercepter un événement tactile au niveau parent et View.onTouchListener / View.onTouchEvent pour la gestion de l'événement principal.
Dans l'ensemble, son design trop compliqué imo mais les apis android se tournent davantage vers la flexibilité que la simplicité.
Parce que c'est le premier résultat sur Google. Je veux partager avec vous un excellent Talk de Dave Smith sur Youtube: Maîtriser le système tactile Android et les diapositives sont disponibles ici . Cela m'a permis de bien comprendre le système Android Touch:
Comment les poignées d' activité se touchent:
Comment les poignées de vue se touchent:
Comment un ViewGroup gère le toucher:
Il fournit également un exemple de code de contact personnalisé sur github.com/devunwired/ .
Réponse: Fondamentalement, le
dispatchTouchEvent()
est appelé sur chaqueView
couche pour déterminer si unView
est intéressé par un geste en cours. Dans unViewGroup
l'ViewGroup
a la capacité de voler les événements tactiles dans sondispatchTouchEvent()
-method, avant qu'il appelleraitdispatchTouchEvent()
les enfants. LeViewGroup
ne stopperait la répartition que si laViewGroup
onInterceptTouchEvent()
méthode-renvoie true. La différence est qu'ildispatchTouchEvent()
s'agit de la répartitionMotionEvents
etonInterceptTouchEvent
indique s'il doit intercepter (pas la distributionMotionEvent
aux enfants) ou non (la distribution aux enfants) .Vous pourriez imaginer le code d'un ViewGroup faire plus ou moins cela (très simplifié):
la source
Réponse supplémentaire
Voici quelques compléments visuels aux autres réponses. Ma réponse complète est ici .
La
dispatchTouchEvent()
méthode d'unViewGroup
utiliseonInterceptTouchEvent()
pour choisir s'il doit immédiatement gérer l'événement tactile (aveconTouchEvent()
) ou continuer à notifier lesdispatchTouchEvent()
méthodes de ses enfants.la source
Il y a beaucoup de confusion au sujet de ces méthodes, mais ce n'est en fait pas si compliqué. La confusion est principalement due au fait que:
View/ViewGroup
ou l'un de ses enfants ne retourne pas vraionTouchEvent
,dispatchTouchEvent
etonInterceptTouchEvent
sera UNIQUEMENT appeléMotionEvent.ACTION_DOWN
. Sans true fromonTouchEvent
, la vue parent supposera que votre vue n'a pas besoin de MotionEvents.MotionEvent.ACTION_DOWN
, même si votre ViewGroup retourne true dansonTouchEvent
.L'ordre de traitement est comme ceci:
dispatchTouchEvent
est appelé.onInterceptTouchEvent
est appeléMotionEvent.ACTION_DOWN
ou lorsqu'un des enfants du ViewGroup a renvoyé true dansonTouchEvent
.onTouchEvent
est d'abord appelé sur les enfants du ViewGroup et quand aucun des enfants ne retourne vrai, il est appelé sur leView/ViewGroup
.Si vous souhaitez prévisualiser
TouchEvents/MotionEvents
sans désactiver les événements sur vos enfants, vous devez faire deux choses:dispatchTouchEvent
pour prévisualiser l'événement et revenirsuper.dispatchTouchEvent(ev)
;onTouchEvent
et retournez vrai, sinon vous n'en obtiendrez pasMotionEvent
saufMotionEvent.ACTION_DOWN
.Si vous souhaitez détecter un geste comme un événement de balayage, sans désactiver d'autres événements sur vos enfants tant que vous n'avez pas détecté le geste, vous pouvez le faire comme ceci:
onInterceptTouchEvent
lorsque votre indicateur est défini pour annuler le traitement MotionEvent par vos enfants. C'est également un endroit pratique pour réinitialiser votre indicateur, car onInterceptTouchEvent ne sera plus appelé avant le prochainMotionEvent.ACTION_DOWN
.Exemple de remplacements dans un
FrameLayout
(mon exemple en est C # car je programme avec Xamarin Android, mais la logique est la même en Java):la source
Je suis tombé sur une explication très intuitive sur cette page Web http://doandroids.com/blogs/tag/codeexample/ . Tiré de là:
la source
dispatchTouchEvent gère avant onInterceptTouchEvent.
En utilisant cet exemple simple:
Vous pouvez voir que le journal sera comme:
Donc, si vous travaillez avec ces 2 gestionnaires, utilisez dispatchTouchEvent pour gérer en première instance l'événement, qui ira à onInterceptTouchEvent.
Une autre différence est que si dispatchTouchEvent retourne 'false', l'événement ne se propage pas à l'enfant, dans ce cas le EditText, alors que si vous retournez false dans onInterceptTouchEvent, l'événement est toujours distribué au EditText
la source
Réponse courte:
dispatchTouchEvent()
sera appelée en premier .Petit conseil: ne doit pas passer outre
dispatchTouchEvent()
car il est difficile à contrôler, cela peut parfois ralentir vos performances. À mon humble avis, je suggère de passer outreonInterceptTouchEvent()
.Parce que la plupart des réponses mentionnent assez clairement l'événement de flux tactile sur l'activité / voir le groupe / la vue, j'ajoute seulement plus de détails sur le code de ces méthodes dans
ViewGroup
(ignorerdispatchTouchEvent()
):onInterceptTouchEvent()
sera appelé en premier, l'événement ACTION sera appelé respectivement en bas -> déplacer -> en haut. Il y a 2 cas:Si vous retournez false dans 3 cas (ACTION_DOWN, ACTION_MOVE, ACTION_UP), il considérera que le parent n'aura pas besoin de cet événement tactile , donc
onTouch()
des parents n'appelle jamais , maisonTouch()
des enfants appellent à la place ; cependant veuillez noter:onInterceptTouchEvent()
continuent de recevoir un événement tactile, tant que leurs enfants n'appellent pasrequestDisallowInterceptTouchEvent(true)
.onTouch()
parents.Inversement, si vous revenez vrai , le parent volera cet événement tactile immédiatement et
onInterceptTouchEvent()
s'arrêtera immédiatement, au lieuonTouch()
des parents seront appelés ainsi que tous lesonTouch()
enfants recevront le dernier événement d'action - ACTION_CANCEL (ainsi, cela signifie que les parents a volé un événement tactile, et les enfants ne peuvent plus le gérer à partir de là). Le flux deonInterceptTouchEvent()
retour false est normal, mais il y a un peu de confusion avec return true case, donc je l'énumère ici:onTouch()
des parents recevront à nouveau ACTION_DOWN et les actions suivantes (ACTION_MOVE, ACTION_UP).onTouch()
des parents recevront ACTION_MOVE suivant (pas le même ACTION_MOVE dansonInterceptTouchEvent()
) et les actions suivantes (ACTION_MOVE, ACTION_UP).onTouch()
des parents ne seront PAS appelés du tout car il est trop tard pour que les parents volent l'événement tactile.Une autre chose importante est ACTION_DOWN de l'événement
onTouch()
qui déterminera si la vue souhaite recevoir plus d'actions de cet événement ou non. Si la vue retourne vrai à ACTION_DOWN dansonTouch()
, cela signifie que la vue est prête à recevoir plus d'actions de cet événement. Sinon, retourner false à ACTION_DOWN inonTouch()
impliquera que la vue ne recevra plus aucune action de cet événement.la source
Vous pouvez trouver la réponse dans cette vidéo https://www.youtube.com/watch?v=SYoN-OvdZ3M&list=PLonJJ3BVjZW6CtAMbJz1XD8ELUs1KXaTD&index=19 et les 3 vidéos suivantes. Tous les événements tactiles sont très bien expliqués, c'est très clair et plein d'exemples.
la source
Le code suivant dans une sous-classe ViewGroup empêcherait ses conteneurs parents de recevoir des événements tactiles:
J'ai utilisé cela avec une superposition personnalisée pour empêcher les vues d'arrière-plan de répondre aux événements tactiles.
la source
La principale différence:
la source
ViewGroup
onInterceptTouchEvent()
est toujours le point d'entrée pour l'ACTION_DOWN
événement qui est le premier événement à se produire.Si vous souhaitez que ViewGroup traite ce geste, retournez true à partir de
onInterceptTouchEvent()
. De retour vrai, ViewGroup deonTouchEvent()
recevra tous les événements qui ont suivi jusqu'à la prochaineACTION_UP
ouACTION_CANCEL
, et dans la plupart des cas, les événements tactiles entreACTION_DOWN
etACTION_UP
ouACTION_CANCEL
sontACTION_MOVE
, qui sera normalement reconnu comme le défilement / gestes jeter.Si vous retournez false de
onInterceptTouchEvent()
, la vue cibleonTouchEvent()
sera appelée. Il sera répété pour les messages suivants jusqu'à ce que vous reveniez vraionInterceptTouchEvent()
.Source: http://neevek.net/posts/2013/10/13/implementing-onInterceptTouchEvent-and-onTouchEvent-for-ViewGroup.html
la source
Activity et View ont tous deux la méthode dispatchTouchEvent () et onTouchEvent. Le ViewGroup a également ces méthodes, mais a une autre méthode appelée onInterceptTouchEvent. Le type de retour de ces méthodes est booléen, vous pouvez contrôler l'itinéraire de répartition via la valeur de retour.
L'envoi de l'événement dans Android commence à partir de Activity-> ViewGroup-> View.
la source
la source
Petite réponse:
onInterceptTouchEvent précède setOnTouchListener.
la source