2012-09-13 11 views
7

Sé cómo detectar un evento táctil de doble clic y uno de dos dedos, pero ¿cómo puedo combinarlos para que reaccionen, así que alguien tiene que hacer doble clic con dos dedos?¿Cómo implementar un doble clic de dos dedos en Android?

De forma predeterminada, Android tiene la presión prolongada para actuar como una segunda forma de hacer clic, pero específicamente estoy buscando un doble clic de dos dedos.

Respuesta

14

yo queríamos un simple y interfaz reutilizable que escucha dos pulsaciones dobles de dedo y beh Aves como GestureDetector. Por lo que se podía utilizar de esta manera (todos cortados & pasta de código ejecutable):

public class Example extends Activity { 
    SimpleTwoFingerDoubleTapDetector multiTouchListener = new SimpleTwoFingerDoubleTapDetector() { 
     @Override 
     public void onTwoFingerDoubleTap() { 
      // Do what you want here, I used a Toast for demonstration 
      Toast.makeText(Example.this, "Two Finger Double Tap", Toast.LENGTH_SHORT).show(); 
     } 
    }; 

    // Override onCreate() and anything else you want 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     if(multiTouchListener.onTouchEvent(event)) 
      return true; 
     return super.onTouchEvent(event); 
    } 
} 

creé SimpleTwoFingerDoubleTapDetector. (Es un nombre largo, pero es descriptiva Puede cambiar el nombre como cualquier cosa que desee..) Registrar este nuevo archivo dentro de su proyecto o como una biblioteca:

public abstract class SimpleTwoFingerDoubleTapDetector { 
    private static final int TIMEOUT = ViewConfiguration.getDoubleTapTimeout() + 100; 
    private long mFirstDownTime = 0; 
    private boolean mSeparateTouches = false; 
    private byte mTwoFingerTapCount = 0; 

    private void reset(long time) { 
     mFirstDownTime = time; 
     mSeparateTouches = false; 
     mTwoFingerTapCount = 0; 
    } 

    public boolean onTouchEvent(MotionEvent event) { 
     switch(event.getActionMasked()) { 
     case MotionEvent.ACTION_DOWN: 
      if(mFirstDownTime == 0 || event.getEventTime() - mFirstDownTime > TIMEOUT) 
       reset(event.getDownTime()); 
      break; 
     case MotionEvent.ACTION_POINTER_UP: 
      if(event.getPointerCount() == 2) 
       mTwoFingerTapCount++; 
      else 
       mFirstDownTime = 0; 
      break; 
     case MotionEvent.ACTION_UP: 
      if(!mSeparateTouches) 
       mSeparateTouches = true; 
      else if(mTwoFingerTapCount == 2 && event.getEventTime() - mFirstDownTime < TIMEOUT) { 
       onTwoFingerDoubleTap(); 
       mFirstDownTime = 0; 
       return true; 
      } 
     }    

     return false; 
    } 

    public abstract void onTwoFingerDoubleTap(); 
} 

En primer lugar, algunas notas sobre Android (de uno táctil) GestureDetector:

  • caso de Android onDoubleTap() utiliza un valor de tiempo de espera estándar de ViewConfiguration. Me refiero a la misma hora.
  • Miden el tiempo transcurrido desde el evento de dedo hacia abajo del primer toque hasta el evento de dedo hacia abajo del segundo toque, y luego emiten onDoubleTap() y onDoubleTapEvent().
    • onDoubleTap() se dispara solo cuando se produce el evento del dedo hacia abajo del segundo toque.
    • onDoubleTapEvent() se activa para cada acción en el segundo toque: abajo, mover y arriba.

Algunas notas sobre SimpleTwoFingerDoubleTapDetector:

  • Mi tiempo de espera se mide desde el primer evento con los dedos hasta el último dedo hasta caso para evitar falsas notificaciones de doble tap . Agregué un poco de tiempo adicional al tiempo de espera de doble toque predeterminado de ViewConfiguration para dar cuenta de esto.
  • El GestureDetector de Android mide slop (qué tan separados están los dos toques). No vi la necesidad de esto aquí, ni controlé la distancia entre los dos dedos en cada toque.
  • Solo transmití un evento onTwoFingerDoubleTap().

Nota final: Puede fácilmente cambio esta a comportarse como un OnTouchListener:

  1. definición de Cambio SimpleTwoFingerDoubleTapDetector:

    public abstract class SimpleTwoFingerDoubleTapListener implements OnTouchListener { 
    
  2. Añadir una nueva variable de clase:

    private View mFirstView; 
    
  3. Cambiar el caso ACTION_DOWN:

    case MotionEvent.ACTION_DOWN: 
        if(mFirstDownTime == -1 || mFirstView != v || hasTimedOut(event.getEventTime())) { 
         mFirstView = v; 
         reset(event.getDownTime()); 
        } 
        break; 
    
  4. Pass mFirstView dentro de la caja ACTION_UP:

    onTwoFingerDoubleTap(mFirstView); 
    
  5. pasado, cambie el método onTwoFingerDoubleTap() para reflejar los cuales Ver fue aprovechado:

    public abstract void onTwoFingerDoubleTap(View v); 
    
+0

Esta respuesta ¡es increíble! – dowi

+2

He intentado este código (¡gracias!) Y no funcionó, solo recibía ACTION_DOWN eventos. Creo que la función onTouchEvent() debe devolver True (para ACTION_DOWN) o de lo contrario ACTION_UP no se recibirá después. Consulte: http://stackoverflow.com/a/16495363/1277048 – FuzzyAmi

1

Este es un oyente de doble clic que creé para detectar un doble clic de dos dedos.

Las variables utilizadas:

private GestureDetector gesture; 
private View.OnTouchListener gestureListener; 
boolean click1 = false; 
boolean click2 = false; 
long first = 0; 
long second = 0; 

En los eventos de toque de onCreate() para registrar la actividad:

gesture = new GestureDetector(getApplicationContext(), new SimpleOnGestureListener(){ 
    public boolean onDown(MotionEvent event) { 
     return true; 
    } 
}); 
gestureListener = new View.OnTouchListener() { 
    @Override 
    public boolean onTouch(View v, MotionEvent event) { 
     return gesture.onTouchEvent(event); 
    } 
}; 

Fuera de onCreate() dentro de la actividad:

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    try { 
     int action = event.getAction() & MotionEvent.ACTION_MASK; 
     //capture the event when the user lifts their fingers, not on the down press 
     //to make sure they're not long pressing 
     if (action == MotionEvent.ACTION_POINTER_UP) { 
      //timer to get difference between clicks 
      Calendar now = Calendar.getInstance(); 

      //detect number of fingers, change to 1 for a single-finger double-click, 3 for a triple-finger double-click, etc. 
      if (event.getPointerCount() == 2) { 
       if (!click1) { 
        //if this is the first click, then there hasn't been a second 
        //click yet, also record the time 
        click1 = true; 
        click2 = false; 
        first = now.getTimeInMillis(); 
       } else if (click1) { 
        //if this is the second click, record its time 
        click2 = true; 
        second = now.getTimeInMillis(); 

        //if the difference between the 2 clicks is less than 500 ms (1/2 second) 
        //Math.abs() is used because you need to be able to detect any sequence of clicks, rather than just in pairs of two 
        //(e.g. click1 could be registered as a second click if the difference between click1 and click2 > 500 but 
        //click2 and the next click1 is < 500) 
        if (Math.abs(second-first) < 500) { 

         //do something!!!!!! 

        } else if (Math.abs(second-first) >= 500) { 
         //reset to handle more clicks 
         click1 = false; 
         click2 = false; 
        } 
       } 
      } 
     } 
    } catch (Exception e){ 

    } 
    return true; 
} 
+0

funciona una sola vez por primera vez. – Nezam

+0

'if (click1 && click2 && Math.abs (second-first) <500) {...}' es overkill. No puede acceder a esta parte específica del código a menos que 'click1 && click2' ya sea verdadero. Para llegar aquí, debe pasar por esto: 'if (click1) {click2 = true; ...} '. El mismo efecto se puede lograr con 'if (Math.abs (second-first) <500) {// ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡hacer algo !!!!!! } else {click1 = false; click2 = false;} ' –

+0

@Nezam Hace años que no uso este código, pero no estoy seguro de por qué eso funcionó bien en nuestra aplicación – WOUNDEDStevenJones

Cuestiones relacionadas