2012-09-13 13 views
7

So come rilevare un doppio tocco e un evento di tocco a due dita, ma come posso combinarli per reagire in modo che qualcuno debba fare doppio clic con due dita?Come implementare un doppio clic con due dita in Android?

Per impostazione predefinita, Android ha la lunga pressione di agire come una seconda forma di clic, ma sono specificamente alla ricerca di un doppio clic con due dita.

risposta

14

Volevo un semplice e interfaccia riutilizzabile che ascolta i due tap e il beh di due dita aves come GestureDetector. In modo che si potrebbe usare in questo modo (tutto tagliato & incollare il codice eseguibile):

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

ho creato SimpleTwoFingerDoubleTapDetector. (E 'un nome lungo, ma è descrittiva È possibile rinominare come tutto quello che vuoi..) Salvare questo nuovo file all'interno del vostro progetto o come libreria:

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

In primo luogo, alcune note su Android (one touch) GestureDetector:

  • evento di Android onDoubleTap() utilizza un valore di timeout standard dal ViewConfiguration. Mi riferisco allo stesso tempo.
  • Misurano il tempo trascorso dall'evento finger-down del primo rubinetto all'evento finger-down del secondo rubinetto, quindi trasmettono onDoubleTap() e onDoubleTapEvent().
    • onDoubleTap() viene generato solo quando si verifica l'evento finger-down del secondo rubinetto.
    • onDoubleTapEvent() viene attivato per ogni azione dal secondo tocco: giù, sposta e su.

Alcune note su SimpleTwoFingerDoubleTapDetector:

  • mio timeout viene misurata dal primo evento dito fino all'ultimo dito fino evento per evitare falsi notifiche double-tap . Ho aggiunto un po 'di tempo extra al timeout del doppio tap di ViewConfiguration predefinito per tener conto di ciò.
  • GestureDetector di Android misura slop (quanto distano i due tocchi). Non ho visto il bisogno di questo qui, né ho controllato la distanza tra le due dita su ogni rubinetto.
  • Trasmetto solo un evento onTwoFingerDoubleTap().

Nota finale: Puoi facilmente cambiamento questo a comportarsi come un OnTouchListener:

  1. definizione di Cambio SimpleTwoFingerDoubleTapDetector:

    public abstract class SimpleTwoFingerDoubleTapListener implements OnTouchListener { 
    
  2. Aggiungi un nuova variabile di classe:

    private View mFirstView; 
    
  3. Modificare il ACTION_DOWN caso:

    case MotionEvent.ACTION_DOWN: 
        if(mFirstDownTime == -1 || mFirstView != v || hasTimedOut(event.getEventTime())) { 
         mFirstView = v; 
         reset(event.getDownTime()); 
        } 
        break; 
    
  4. Passo mFirstView all'interno del ACTION_UP caso:

    onTwoFingerDoubleTap(mFirstView); 
    
  5. ultimo, il cambio del metodo onTwoFingerDoubleTap() per riflettere che Visualizza è stato toccato:

    public abstract void onTwoFingerDoubleTap(View v); 
    
+0

Questa risposta è fantastico! – dowi

+2

Ho provato questo codice (grazie!) E non ha funzionato - stavo solo ricevendo eventi ACTION_DOWN. Credo che la funzione onTouchEvent() debba restituire True (per ACTION_DOWN) altrimenti ACTION_UP non verrà ricevuto successivamente. Fare riferimento a: http://stackoverflow.com/a/16495363/1277048 – FuzzyAmi

1

Questo è un ascoltatore doppio clic che ho creato per rilevare un doppio clic con due dita.

Variabili utilizzate:

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

nel tocco eventi della onCreate() di registrare attività:

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

di fuori del onCreate() all'interno dell'attività:

@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

funziona Solo una volta per la prima volta. – Nezam

+0

'if (click1 && click2 && Math.abs (secondo prima) <500) {...}' è eccessivo. Non puoi accedere a questa particolare parte del codice a meno che 'click1 && click2' sia già vero. Per arrivare qui, devi passare attraverso questo: 'if (click1) {click2 = true; ...} '. Lo stesso effetto può essere ottenuto con 'if (Math.abs (secondo-primo) <500) {// fa qualcosa !!!!!! } else {click1 = falso; click2 = false;} ' –

+0

@Nezam Non ho usato questo codice da anni, ma non sono sicuro del perché sarebbe - ha funzionato bene nella nostra app – WOUNDEDStevenJones

Problemi correlati