开发者

Why android onLongPress always is fired after onDoubleTap?

I have onLongPress and onDoubleTap actions placed on the button according to this code:

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

I always see onLongPress fired after onDoubleClick fired and executed. What is the reason of such counterintuitive behavior and how to avoid it?

UPDATED I have changed my source code to be more specific

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

This is a log after onDoubleTap I clicked. You can see onLongPress at the end - I never click it.

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

UPDATE I have found the solution. To avoid onLongPress firing two changes needs to be done:

First: detector.setIsLongpressEnabled开发者_JAVA百科(true); in onTouch(View v, MotionEvent event)

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

Second: add detector.setIsLongpressEnabled(false); in 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;
    }


Technically this shouldn't happen

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

because on the ACTION_DOWN or ACTION_UP event, all of the LONG_PRESS messages events are removed from the queue. So on the second tap the following code will remove the long press events.

 mHandler.removeMessages(LONG_PRESS);

Ninja edit : hacky workaround for your problem

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


You see always the onLongPress fired because in your code you launch an intent before of consuming the onDoubleTap event.
You can disable onLongPress by
public void setIsLongpressEnabled (boolean isLongpressEnabled)
and use the onDown method for performing your action.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜