Comment attraper les événements double tap dans l'utilisation Android OnTouchListener

StackOverflow https://stackoverflow.com/questions/7314579

  •  26-10-2019
  •  | 
  •  

Question

Je suis en train de rattraper les événements à double tap à l'aide OnTouchListener. Je me dis que je mettrais un long pour motionEvent.ACTION_DOWN, et un autre long pour une deuxième motionEvent.ACTION_DOWN et mesurer le temps entre les deux d'entre eux et faire quelque chose avec elle. Cependant, j'ai du mal à comprendre exactement comment aborder ce sujet. J'utilise des cas de commutation pour ramasser des événements multitouch, donc je préfère ne pas essayer de rééquiper tout cela pour mettre en œuvre GestureDetector (et, malheureusement, il est impossible de mettre en œuvre à la fois ontouchlistener et Gesturedetector simultanément). Toutes les idées contribueraient grandement:

i.setOnTouchListener(new OnTouchListener() {

        public boolean onTouch(View v, MotionEvent event) {


                  ImageView i = (ImageView) v;

                  switch (event.getAction() & MotionEvent.ACTION_MASK) {


                  case MotionEvent.ACTION_DOWN:
                      long firstTouch = System.currentTimeMillis();
                     ///how to grab the second action_down????

                     break;
Était-ce utile?

La solution

J'ai abordé ce problème plus tôt. Il consiste à utiliser un gestionnaire d'attendre un certain laps de temps d'attendre le second clic: Comment puis-je créer un seul clic de l'événement et cliquez deux fois sur l'événement lorsque le bouton Menu est pressé?

Autres conseils

Dans votre définition de la classe:

public class main_activity extends Activity
{
    //variable for counting two successive up-down events
   int clickCount = 0;
    //variable for storing the time of first click
   long startTime;
    //variable for calculating the total time
   long duration;
    //constant for defining the time duration between the click that can be considered as double-tap
   static final int MAX_DURATION = 500;
}

Ensuite, dans votre corps de classe:

OnTouchListener MyOnTouchListener = new OnTouchListener()
{
    @Override
    public boolean onTouch (View v, MotionEvent event)
    {
        switch(event.getAction() & MotionEvent.ACTION_MASK)
        {
        case MotionEvent.ACTION_DOWN:
            startTime = System.currentTimeMillis();
            clickCount++;
            break;
        case MotionEvent.ACTION_UP:
            long time = System.currentTimeMillis() - startTime;
            duration=  duration + time;
            if(clickCount == 2)
            {
                if(duration<= MAX_DURATION)
                {
                    Toast.makeText(captureActivity.this, "double tap",Toast.LENGTH_LONG).show();
                }
                clickCount = 0;
                duration = 0;
                break;             
            }
        }
    return true;    
    }
}

a été adapté d'une réponse: DoubleTap dans android par https://stackoverflow.com/users/1395802/karn

Avec la classe aide SimpleGestureListener qui implémente l'GestureListener et OnDoubleTapListener vous ne avez pas besoin beaucoup à faire.

yourView.setOnTouchListener(new OnTouchListener() {
private GestureDetector gestureDetector = new GestureDetector(Test.this, new GestureDetector.SimpleOnGestureListener() {
    @Override
    public boolean onDoubleTap(MotionEvent e) {
        Log.d("TEST", "onDoubleTap");
        return super.onDoubleTap(e);
    }
    ... // implement here other callback methods like onFling, onScroll as necessary
});

@Override
public boolean onTouch(View v, MotionEvent event) {
    Log.d("TEST", "Raw event: " + event.getAction() + ", (" + event.getRawX() + ", " + event.getRawY() + ")");
    gestureDetector.onTouchEvent(event);
    return true;
}});

C'est beaucoup easyer:

//variable for storing the time of first click
long startTime;
//constant for defining the time duration between the click that can be considered as double-tap
static final int MAX_DURATION = 200;

    if (event.getAction() == MotionEvent.ACTION_UP) {

        startTime = System.currentTimeMillis();             
    }
    else if (event.getAction() == MotionEvent.ACTION_DOWN) {

        if(System.currentTimeMillis() - startTime <= MAX_DURATION)
        {
            //DOUBLE TAP
        }       
    }

Voici ma solution.

Il était important pour moi d'avoir un rapide et une séparation claire de « simple pression » et « double tap ». J'ai essayé GestureDetector d'abord, mais avait de très mauvais résultats. Peut-être en raison de mon utilisation imbriquée de scrollviews - qui sait ...

Je me concentre sur MotionEvent.ACTION_UP et l'ID de l'élément taraudé. Pour garder la première prise en vie je utiliser un Handler envoyer un message retardé (de 350ms) afin que l'utilisateur a un certain temps pour placer son deuxième coup sur la ImageView. Si l'utilisateur a placé un second robinet sur un élément avec l'identifiant identique je prends ce que le double tap, supprimer le message retardé et rund mon code personnalisé pour « taper deux fois ». Si l'utilisateur a placé un robinet sur un élément avec un autre ID Je prends cela comme nouveau robinet et créer un autre Handler pour elle.

classe des variables globales

private int tappedItemId = -1;
Handler myTapHandler;
final Context ctx = this;

Exemple de code

ImageView iv = new ImageView(getApplicationContext());
//[...]
iv.setId(i*1000+n);
iv.setOnTouchListener(new View.OnTouchListener() {

@Override
public boolean onTouch(View v, MotionEvent event) {

   switch (event.getAction()) {

      case MotionEvent.ACTION_UP: {

         //active 'tap handler' for current id?
         if(myTapHandler != null && myTapHandler.hasMessages(v.getId())) {

            // clean up (to avoid single tap msg to be send and handled)
            myTapHandler.removeMessages(tappedItemId);
            tappedItemId = -1;

            //run 'double tap' custom code
            Toast.makeText(ScrollView.this, "double tap on "+v.getId(), Toast.LENGTH_SHORT).show();

            return true;
         } else {
            tappedItemId = v.getId();
            myTapHandler = new Handler(){
               public void handleMessage(Message msg){
                  Toast.makeText(ctx, "single tap on "+ tappedItemId + " msg 'what': " + msg.what, Toast.LENGTH_SHORT).show();
               }
            };

            Message msg = Message.obtain();
            msg.what = tappedItemId;
            msg.obj = new Runnable() {
               public void run() {
                  //clean up
                  tappedItemId = -1;
               }
            };
            myTouchHandler.sendMessageDelayed(msg, 350); //350ms delay (= time to tap twice on the same element)
         }
         break;
      }
   }

   return true;
 }
});
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top