I know how to detect a double-click and a two-finger touch event, but how can I combine these to react so somebody needs to double click with two fingers?
By default, Android has the long press to act as a second form of clicking, but I'm specifically looking for a two-finger double-click.
I wanted a simple and reusable interface that listens for two finger double taps and behaves like GestureDetector. So that you could use it like this (all cut & paste runnable code):
public class Example extends Activity {
SimpleTwoFingerDoubleTapDetector multiTouchListener = new SimpleTwoFingerDoubleTapDetector() {
@Override
public void onTwoFingerDoubleTap() {
// Do what you want here, I used a Toast for demonstration
Toast.makeText(Example.this, "Two Finger Double Tap", Toast.LENGTH_SHORT).show();
}
};
// Override onCreate() and anything else you want
@Override
public boolean onTouchEvent(MotionEvent event) {
if(multiTouchListener.onTouchEvent(event))
return true;
return super.onTouchEvent(event);
}
}
I created SimpleTwoFingerDoubleTapDetector. (It's a long name, but it is descriptive. You can rename it as anything you want.) Save this new file inside your project or as a library:
public abstract class SimpleTwoFingerDoubleTapDetector {
private static final int TIMEOUT = ViewConfiguration.getDoubleTapTimeout() + 100;
private long mFirstDownTime = 0;
private boolean mSeparateTouches = false;
private byte mTwoFingerTapCount = 0;
private void reset(long time) {
mFirstDownTime = time;
mSeparateTouches = false;
mTwoFingerTapCount = 0;
}
public boolean onTouchEvent(MotionEvent event) {
switch(event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
if(mFirstDownTime == 0 || event.getEventTime() - mFirstDownTime > TIMEOUT)
reset(event.getDownTime());
break;
case MotionEvent.ACTION_POINTER_UP:
if(event.getPointerCount() == 2)
mTwoFingerTapCount++;
else
mFirstDownTime = 0;
break;
case MotionEvent.ACTION_UP:
if(!mSeparateTouches)
mSeparateTouches = true;
else if(mTwoFingerTapCount == 2 && event.getEventTime() - mFirstDownTime < TIMEOUT) {
onTwoFingerDoubleTap();
mFirstDownTime = 0;
return true;
}
}
return false;
}
public abstract void onTwoFingerDoubleTap();
}
First, a few notes about Android (one-touch) GestureDetector:
onDoubleTap()
event uses a standard timeout value from ViewConfiguration. I refer to the same time.onDoubleTap()
and onDoubleTapEvent()
.
onDoubleTap()
is fired only when the second tap's finger-down event occurs.onDoubleTapEvent()
is fired for every action by the second tap: down, move, and up.A few notes on SimpleTwoFingerDoubleTapDetector:
onTwoFingerDoubleTap()
. Final note: You can easily change this to behave like an OnTouchListener:
Change SimpleTwoFingerDoubleTapDetector's definition:
public abstract class SimpleTwoFingerDoubleTapListener implements OnTouchListener {
Add a new class variable:
private View mFirstView;
Change the ACTION_DOWN
case:
case MotionEvent.ACTION_DOWN:
if(mFirstDownTime == -1 || mFirstView != v || hasTimedOut(event.getEventTime())) {
mFirstView = v;
reset(event.getDownTime());
}
break;
Pass mFirstView
inside the ACTION_UP
case:
onTwoFingerDoubleTap(mFirstView);
Last, change the onTwoFingerDoubleTap()
method to reflect which View was tapped:
public abstract void onTwoFingerDoubleTap(View v);