2011-09-30 31 views
12

Tôi có onLongPress và hành động onDoubleTap đặt trên nút theo mã này:Tại sao android onLongPress luôn được kích hoạt sau khi bậtDoubleTap?

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

Tôi luôn thấy onLongPress sa thải sau khi bị sa thải onDoubleClick và thực thi. Lý do của hành vi phản trực giác như thế nào và cách tránh nó?

CẬP NHẬT Tôi đã thay đổi mã nguồn của tôi để cụ thể hơn

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

Đây là nhật sau onDoubleTap tôi nhấp. Bạn có thể thấy onLongPress ở cuối - tôi không bao giờ nhấp vào nó.

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 ************* 

CẬP NHẬT Tôi đã tìm thấy giải pháp. Để tránh onLongPress bắn hai thay đổi cần phải được thực hiện:

Đầu tiên: detector.setIsLongpressEnabled (đúng); trong onTouch (Xem v, MotionEvent sự kiện)

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

Thứ hai: thêm detector.setIsLongpressEnabled (sai); trong 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

Không thể lặp lại điều này, xin lỗi. Sử dụng Log.i() trên 2 sự kiện đó, chúng được gọi chính xác. –

+0

làm việc phong nha xung quanh cho những gì có vẻ như một điều kiện cuộc đua được xây dựng trong như được mô tả trong các ý kiến ​​của câu trả lời được chấp nhận. cảm ơn. –

Trả lời

3

Về mặt kỹ thuật này không nên xảy ra

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

vì trên các sự kiện ACTION_DOWN hoặc ACTION_UP, tất cả các thông điệp LONG_PRESS sự kiện được lấy ra khỏi hàng đợi. Vì vậy, vào lần nhấn thứ hai, mã sau sẽ xóa các sự kiện báo chí dài.

mHandler.removeMessages(LONG_PRESS); 

Ninja chỉnh sửa: workaround hacky cho vấn đề của bạn

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

Như tôi đã tìm thấy ngay bây giờ, tôi luôn luôn nhận được onLongPress bắn sau khi onDoubleTap ** chỉ dưới debugger ** nếu điểm vi phạm được thiết lập trên phương pháp onDoubleClick. Nếu tôi xóa điểm vi phạm - tất cả đều OK ... – isabsent

+1

Điều đó có ý nghĩa sau đó, 'mCurrentDownEvent.getDownTime() + tapTime + longpressTime' đã hết hạn sau đó – Reno

+0

Dường như nếu tôi có cơ sở xử lý thời gian dài trong phương pháp onDoubleTap, tôi luôn sẽ được onLongPress bắn? – isabsent

0

Bạn thấy lúc nào cũng là onLongPress sa thải vì trong mã của bạn, bạn khởi động một ý định trước khi tiêu thụ các sự kiện onDoubleTap.
Bạn có thể tắt onLongPress theo
public void setIsLongpressEnabled (boolean isLongpressEnabled)
và sử dụng phương thức onDown để thực hiện tác vụ của bạn.

Các vấn đề liên quan