web-dev-qa-db-fra.com

OnTouchEvent ne fonctionne pas sur les vues enfant

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

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


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


   break;
   }
   return true;

  }
25
user1438128

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. Activity.dispatchTouchEvent ()
  2. ViewGroup.dispatchTouchEvent ()
  3. View.dispatchTouchEvent ()
  4. View.onTouchEvent ()
  5. ViewGroup.onTouchEvent ()
  6. Activity.onTouchEvent ()

Mais les événements suivent uniquement la chaîne jusqu'à ce qu'ils soient consommés (ce qui signifie que quelqu'un retourne true à partir de onTouchEvent() ou un écouteur). Dans le cas où vous touchez quelque part sur l'écran, l'événement ne l'intéresse pas, il se répercute donc dans votre code. Cependant, dans le cas d'un bouton (ou d'une autre View cliquable), l'événement tactile est touché car il s'y intéresse, le flux s'arrête donc à la ligne 4.

Si vous souhaitez surveiller toutes les touches qui entrent dans votre activité, vous devez remplacer dispatchTouchEvent(), car ce qui est toujours appelé en premier, onTouchEvent() pour une activité, est appelé en dernier et uniquement si personne d'autre n'a capturé l'événement. Veillez toutefois à ne pas utiliser les événements ici, sinon les vues enfant 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 placer votre code de traitement tactile dans une variable ViewGroup (telle que 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 est une interaction qui ne peut être annulée avant le début d'un nouvel événement tactile (une fois que vous volez un événement, vous les volez tous).

HTH

89
Devunwired

Permettez-moi d'ajouter un commentaire supplémentaire à cet excellent message de @Devunwired.

Si vous avez également défini onTouchListener sur votre vue, sa méthode onTouch () sera appelée APRÈS les méthodes d'envoi, mais AVANT toute méthode onTouchEvent (), c'est-à-dire entre les réponses n ° 3 et n ° 4 de @ Devunwired.

4
kouretinho

Essayez de définir l'attribut descendantFocusability de votre présentation sur blocksDescendants

1
Jokahero

vous pouvez aussi essayer onUserInteraction():

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

fonctionne bien pour moi!

0
amdev

Activity::onTouchEvent sera appelé uniquement si aucune des vues de la fenêtre d'activité ne consomme/ne gère l'événement. Si vous touchez la Button, la Button 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 traitement des événements Android Touch.

http://pierrchen.blogspot.jp/2014/03/pipeline-of-Android-touch-event-handling.html

0
pierrotlefou

utilisez public boolean dispatchTouchEvent(MotionEvent event) à la place de onTouchEvent()

0
Asad
RecyclerView list_view = findViewById(R.id.list_view);
list_view.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener(){
    @Override
    public boolean onInterceptTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e) {
        View child = rv.findChildViewUnder(e.getX(), e.getY());
        Log.i("Hello", "World");
        return false;
    }
});
0
Ray Hulha