2014-07-12 2 views
2

Voici mon bouton très standard onTouchListener:bouton Annuler presse si l'utilisateur déplace le doigt sur le bouton

b.setOnTouchListener(new OnTouchListener() { 
    @Override 
    public boolean onTouch(View v, MotionEvent event) { 
     if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN) { 
      b.setPressed(true); 
     } 
     if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP) { 
      b.setPressed(false); 
      // Do the button action stuff here 
     } 
     return true; 
    } 
}); 

Lorsque l'utilisateur appuie sur le bouton I mis sur la touche pour « emboutie ». Lorsque l'utilisateur lève le doigt, je mets le bouton sur "non enfoncé" et ensuite je fais ce que le bouton est supposé faire.

Tout cela est très bien sauf dans le cas où l'utilisateur appuie sur le bouton puis, tout en continuant à garder le doigt vers le bas, déplace le doigt à l'extérieur de la zone du bouton. Lorsque le doigt est levé, le contenu ACTION_UP s'exécute quand même. Je voudrais que ce comportement agisse comme une "annulation" de la pression sur le bouton. Donc, dès que le doigt pressé se déplace en dehors de la zone de bouton, je voudrais b.setPressed(false); et ne pas faire le truc action de bouton lorsque le doigt est levé.

J'ai essayé d'utiliser MotionEvent.ACTION_CANCEL et MotionEvent.ACTION_OUTSIDE (comme suggéré par How to detect when finger slides off the ImageButton?) mais je dois manquer quelque chose parce qu'ils ne fonctionnent pas.

De Detect when a user moves off of a button in Android il semblerait que cela peut être fait avec event.getX() et event.getY(). Si getX() est négatif, vous êtes sur la gauche et si getY() est négatif, vous êtes en haut, mais pour savoir si vous êtes hors de la droite ou du bas, je vais devoir déterminer la taille de la bouton et puis ... il doit y avoir un moyen plus simple. Y a-t-il?

Répondre

3

Vous avez eu la bonne réponse. Utilisez getWidth() et getHeight() pour obtenir la largeur et la hauteur et vérifier si x ou y est supérieur.

ACTION_CANCEL ne fonctionne pas car CANCEL est généré lorsqu'une vue parent prend le contrôle des événements tactiles, comme le fait un ListView lors du défilement. Cela ne se produit que dans certains cas inhabituels où vous le demandez. Il ne va pas être généré pour seulement MOVE ou UP.

+0

Merci. getX() et get (y) ne vont pas être une énorme quantité de travail, mais je suis surpris qu'il n'y ait pas de façon "intégrée" de le faire car cela semble être une fonctionnalité de bouton si évidente. Merci à celui qui a donné la downvote. –

+0

http://stackoverflow.com/questions/14414873/how-to-detect-when-finger-slides-off-the-imagebutton semble décrire une situation similaire et ACTION_CANCEL a apparemment fonctionné. Peut-être que je ne comprends pas ce qui se passe là-bas. –

+0

ACTION_CANCEL est généré lorsqu'une vue parente (comme une vue de défilement ou une vue de liste) prend possession des événements tactiles, comme lorsqu'une vue de défilement pense que vous faites défiler. Sauf si vous êtes dans une vue similaire, vous ne verrez pas une action annuler ici. –

0

Puisque personne n'a posté de code, en voici un. Un booléen est utilisé pour indiquer quand les actions respectives doivent être effectuées.

L'événement MotionEvent.ACTION_MOVE est géré pour vérifier si le doigt est sorti des limites. Si oui, b.setPressed(false); est appelée et le booléen est utilisé pour indiquer que MotionEvent.ACTION_UP ne doit pas être déclenché la prochaine fois, c'est-à-dire pour annuler le clic du bouton.

Et dans MotionEvent.ACTION_UP, appelez b.setPressed(false); seulement si notre booléen n'indique pas un saut (comme mentionné ci-dessus). Et si c'est le cas, inversez le booléen pour que l'action du bouton s'exécute la prochaine fois.

private Boolean notNow = false; 
private Rect rect; // Variable rect to hold the bounds of the view 

b.setOnTouchListener(new OnTouchListener(){ 
    @Override 
    public boolean onTouch(View v, MotionEvent event){ 
     if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN){ 
      b.setPressed(true); 
      rect = new Rect(v.Left, v.Top, v.Right, v.Bottom); 
     } 
     if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP){ 
      if (!notNow){ 
       b.setPressed(false); 
      } 
      else //button press canceled 
       notNow = false; 
     } 
     if((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_MOVE){ 
      if(!notNow) 
       if (!rect.contains(v.getLeft() + (int) event.getX(), v.getTop() + (int) event.getY())){ 
        // finger moved out of bounds 
        b.setPressed(false); 
        notNow = true; //cancel button press the next time 
       } 
     } 

     return true; 
}); 
Questions connexes