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.
精彩评论