2011-09-30 25 views
12

tengo onLongPress y acciones onDoubleTap colocados en el botón de acuerdo con este código:¿Por qué android onLongPress siempre se activa después de onDoubleTap?

... 
GestureDetector detector = new GestureDetector(this, new TapDetector()); 

public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 
    detector = new GestureDetector(this, new TapDetector()); 
    ... 
} 

private class TapDetector extends GestureDetector.SimpleOnGestureListener { 

    @Override 
    public boolean onDoubleTap(MotionEvent e) { 
     // Do something 
     return true; 
    } 

    @Override 
    public void onLongPress(MotionEvent e) {   
     // Do something   
    } 
} 

Button incomeButton = (Button) findViewById(R.id.income); 
button.setOnTouchListener(new OnTouchListener(){ 
    @Override 
    public boolean onTouch(View v, MotionEvent event) { 
     detector.onTouchEvent(event); 
     return true; 
    } 
}); 

Siempre veo onLongPress despedido después OnDoubleClick despedido y ejecutado. ¿Cuál es la razón de tal comportamiento contraintuitivo y cómo evitarlo?

ACTUALIZADO he cambiado de código fuente para ser más específicos

public class MainActivity extends Activity { 
private GestureDetector detector; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 
    detector = new GestureDetector(this, new TapDetector());  

    Button button = (Button) findViewById(R.id.button);     
    button.setOnTouchListener(new OnTouchListener(){ 
     @Override 
     public boolean onTouch(View v, MotionEvent event) { 
      System.out.println("************* onTouch *************"); 
      detector.onTouchEvent(event); 
      return true; 
     } 
    });       
}  

class TapDetector extends GestureDetector.SimpleOnGestureListener { 

    @Override 
    public void onLongPress(MotionEvent e) { 
     System.out.println("************* onLongPress *************");      
    }   

    @Override 
    public boolean onDoubleTap(MotionEvent e) { 
     System.out.println("************* onDoubleTap *************"); 
     Intent intent = new Intent();   
     intent.setClass(getApplicationContext(), NewActivity.class); 
     intent.putExtra("parameterName", "parameter"); 
     startActivity(intent);    
     return true; 
    }    
}   
} 

Este es un registro después de onDoubleTap He hecho clic. Puedes ver en LongPress al final: nunca hago clic en él.

I/System.out(1106): ************* onTouch ************* 
I/System.out(1106): ************* onTouch ************* 
I/System.out(1106): ************* onTouch ************* 
I/System.out(1106): ************* onDoubleTap ************* 
I/ActivityManager( 59): Starting activity: Intent { cmp=my.tapdetector/.NewActivity (has extras) } 
I/ActivityManager( 59): Displayed activity my.tapdetector/.NewActivity: 324 ms (total 324 ms) 
I/System.out(1106): ************* onLongPress ************* 

ACTUALIZACIÓN he encontrado la solución. Para evitar onLongPress disparar dos cambios que hay que hacer:

Primero: detector.setIsLongpressEnabled (cierto); en onTouch (Ver v, caso MotionEvent)

button.setOnTouchListener(new OnTouchListener(){ 
     @Override 
     public boolean onTouch(View v, MotionEvent event) { 
      System.out.println("************* onTouch *************"); 
      detector.onTouchEvent(event); 
      detector.setIsLongpressEnabled(true); 
      return true; 
     } 
    }); 

Segundo: añadir detector.setIsLongpressEnabled (falsa); en onDoubleTap (MotionEvent e)

 public boolean onDoubleTap(MotionEvent e) { 
     detector.setIsLongpressEnabled(false); 
     System.out.println("************* onDoubleTap *************"); 
     Intent intent = new Intent();   
     intent.setClass(getApplicationContext(), NewActivity.class); 
     intent.putExtra("parameterName", "parameter"); 
     startActivity(intent);    
     return true; 
    } 
+0

No se puede repetir esto, lo siento. Usando Log.i() en esos 2 eventos, se llaman correctamente. –

+0

trabajo decente para lo que parece una condición de carrera incorporada como se describe en los comentarios de la respuesta aceptada. Gracias. –

Respuesta

3

Técnicamente esto no debería ocurrir

case MotionEvent.ACTION_DOWN: 
     mLastMotionX = x; 
     mLastMotionY = y; 
     mCurrentDownEvent = MotionEvent.obtain(ev); 
     mAlwaysInTapRegion = true; 
     mInLongPress = false; 

     if (mIsLongpressEnabled) { 
      mHandler.removeMessages(LONG_PRESS); 
      mHandler.sendEmptyMessageAtTime(LONG_PRESS, mCurrentDownEvent.getDownTime() 
        + tapTime + longpressTime); 
     } 
     mHandler.sendEmptyMessageAtTime(SHOW_PRESS, mCurrentDownEvent.getDownTime() + tapTime); 

porque en el caso ACTION_DOWN o ACTION_UP, todos los mensajes LONG_PRESS eventos se elimina de la cola. Por lo tanto, en el segundo toque, el siguiente código eliminará los eventos de pulsación larga.

mHandler.removeMessages(LONG_PRESS); 

Ninja edición: hacky solución para su problema

 @Override 
    public void onLongPress(MotionEvent e) { 
     if(MainActivity.this.hasWindowFocus()) 
     { 
      Log.d("Touchy", "Long tap");  
     } 
    } 
+1

Como encontré hace un momento, siempre obtengo encendido LongPress después de onDoubleTap ** solo bajo depuración ** si el punto de ruptura está activado en el método DoubleClick. Si elimino el punto de ruptura, todo está bien ... – isabsent

+1

Tiene sentido entonces, 'mCurrentDownEvent.getDownTime() + tapTime + longpressTime' ha expirado por entonces – Reno

+0

Parece que tengo un cuerpo de procesamiento de tiempo largo en el método onDoubleTap, siempre se encenderá en LongPress despedido? – isabsent

0

Usted ve siempre la onLongPress despedido porque en su código que inicie un intento antes de consumir el evento onDoubleTap.
Puede desactivar onLongPress por
public void setIsLongpressEnabled (boolean isLongpressEnabled)
y utilizar el método onDown para realizar su acción.

Cuestiones relacionadas