Why android onLongPress always is fired after onDoubleTap?

孤街醉人 提交于 2019-12-18 11:29:14

问题


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

回答1:


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



回答2:


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.



来源:https://stackoverflow.com/questions/7606921/why-android-onlongpress-always-is-fired-after-ondoubletap

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!