OnTouchEvent ne fonctionne pas sur les vues des enfants

J'ai une disposition linéaire qui a un bouton et un TextView dessus. J'ai écrit un OnTouchEvent pour l'activité. Le code fonctionne très bien si je touche sur l'écran, mais si je touche le bouton, le code ne fonctionne pas. Quelle est la solution pour cela?

public boolean onTouchEvent(MotionEvent event) {
   int eventaction=event.getAction();


   switch(eventaction)
   {
   case MotionEvent.ACTION_MOVE:
      reg.setText("hey");


   break;
   }
   return true;

  }
25
demandé sur eldarerathis 2012-06-12 20:58:37

6 réponses

Le problème est l'ordre des opérations pour la façon dont Android gère les événements tactiles. Chaque événement tactile suit le modèle de (exemple simplifié):

  1. activité.dispatchTouchEvent ()
  2. ViewGroup.dispatchTouchEvent ()
  3. vue.dispatchTouchEvent ()
  4. vue.onTouchEvent ()
  5. ViewGroup.onTouchEvent ()
  6. activité.onTouchEvent ()

Mais les événements ne suivent la chaîne que jusqu'à ce qu'ils soient consommés (ce qui signifie que quelqu'un revient true à partir de onTouchEvent() ou d'un écouteur). Dans le cas où vous touchez simplement quelque part sur l'écran, personne n'est intéressé par l'événement, donc il coule jusqu'à votre code. Cependant, dans le cas d'un bouton (ou d'un autre bouton cliquable View), Il consomme l'événement tactile car il s'y intéresse, de sorte que le flux s'arrête à la ligne 4.

Si vous voulez surveiller toutes les touches qui entrent dans votre activité, vous devez remplacer {[3] } puisque ce qui est toujours appelé en premier, onTouchEvent() pour une activité est appelé dernier, et seulement si personne d'autre capturé l'événement. Veillez cependant à ne pas consommer d'événements ici, sinon les vues enfants ne les obtiendront jamais et vos boutons ne seront pas cliquables.

public boolean dispatchTouchEvent(MotionEvent event) {
   int eventaction=event.getAction();

    switch(eventaction) {
      case MotionEvent.ACTION_MOVE:
          reg.setText("hey");
          break;
      default:
          break;
    }

    return super.dispatchTouchEvent(event);
}

Une autre option serait de mettre votre code de gestion tactile dans un ViewGroup personnalisé (comme LinearLayout) et d'utiliser sa méthode onInterceptTouchEvent() pour permettre à la vue parent de voler et de gérer les événements tactiles si nécessaire. Soyez prudent cependant, car cette interaction ne peut pas être annulée jusqu'à ce qu'un nouvel événement tactile commence (une fois que vous voler un événement, vous les volez tous).

HTH

88
répondu Devunwired 2012-06-12 17:29:24

Permettez-moi d'ajouter un commentaire à cet excellent post de @Devunwired.

Si vous avez également défini un onTouchListener sur votre vue, sa méthode onTouch () sera appelée après les méthodes de répartition, mais avant toute méthode onTouchEvent (), c'est-à-dire entre no.3 et no.4 sur la réponse de @Devunwired.

4
répondu kouretinho 2014-01-16 14:47:53

Essayez de définir l'attributdescendantFocusability de votre mise en page sur blocksDescendants

1
répondu Jokahero 2012-06-12 17:01:47

Activity::onTouchEvent sera appelé uniquement lorsque non des vues dans la fenêtre D'activité consomme / gère l'événement. Si vous touchez le Button, le {[1] } consommera les événements, de sorte que l'activité ne pourra pas le gérer.

Consultez les articles suivants pour en savoir plus sur le pipeline de gestion des événements Android Touch.

Http://pierrchen.blogspot.jp/2014/03/pipeline-of-android-touch-event-handling.html

0
répondu pierrotlefou 2014-03-09 03:12:21

Vous pouvez également essayer onUserInteraction():

@Override 
public void onUserInteraction(){
     //your code here
     super.onUserInteraction();
}

Fonctionne bien pour moi!

0
répondu amdev 2016-10-30 11:19:35

Utilisez public boolean dispatchTouchEvent(MotionEvent event) à la place sur onTouchEvent()

0
répondu Asad 2018-10-12 14:12:48