Pregunta

Estoy tratando de atrapar eventos de doble toque usando OnTouchListener. Supongo que establecería mucho para MotionEvent.Action_down, y un largo largo para un segundo MotionEvent.Action_down y medir el tiempo entre los dos y luego hacer algo con él. Sin embargo, estoy teniendo dificultades para averiguar exactamente cómo abordar esto. Estoy usando las cajas de Switch para recoger eventos MultiTouch, por lo que prefiero no tratar de reorganizar todo esto para implementar GestEdEtector (y desafortunadamente es imposible implementar tanto OnTouchListener como GestEdetector simultáneamente). Cualquier idea ayudaría mucho:

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;
¿Fue útil?

Solución

Abordé este problema antes. Implica usar un controlador para esperar una cierta cantidad de tiempo para esperar el segundo clic: ¿Cómo puedo crear un solo evento de clic y hacer doble clic cuando se presiona el botón de menú?

Otros consejos

En tu definición de clase:

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;
}

Luego en tu cuerpo de clase:

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;    
    }
}

Esto fue adaptado de una respuesta en: Doubletap en Android por https://stackoverflow.com/users/1395802/karn

Con la clase Helper SimplegestureListener que implementa GestureListener y OnDoubleTapListener, no necesita mucho que hacer.

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;
}});

Eso es mucho más fácil:

//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
        }       
    }

Aquí está mi solución.

Era importante para mí tener una separación rápida y clara de 'toque único' y 'doble toque'. Lo intenté GestureDetector Primero pero tuve muy malos resultados. Tal vez el resultado de mi uso anidado de vistas de desplazamiento, quién sabe ...

Me concentro en MotionEvent.ACTION_UP y la identificación del elemento golpeado. Para mantener vivo el primer toque, uso un Handler Enviar un mensaje retrasado (350 ms) para que el usuario tenga tiempo para colocar su segundo toque en el ImageView. Si el usuario colocó un segundo toque en un elemento con la ID idéntica, tomo esto como doble toque, elimine el mensaje retrasado y fuje mi código personalizado para 'doble toque'. Si el usuario colocó un toque en un elemento con una identificación diferente, tomo esto como nuevo toque y crea otro Handler para ello.

Variables globales de clase

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

Ejemplo de código

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;
 }
});
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top