问题
I've implemented an OnTouchListener in my MapActivity and of course I had to override the onTouch() method.
I want it to fire only when I tap on the map - otherwise I can't even move the map.
Here's my onTouch method:
@Override
public boolean onTouch(View v, MotionEvent e) {
if (e.getAction() == MotionEvent.ACTION_DOWN) {
// SOME ACTIONS ...
}
return true;
}
回答1:
use:
e.getAction() == MotionEvent.ACTION_UP
and:
e.getAction() == MotionEvent.ACTION_MOVE
if there was and ACTION_UP event after and ACTION_DOWN, and no ACTION_MOVE between, its a tap
UPDATED:
private int mLastMotionEventAction = MotionEvent.ACTION_UP;
@Override
public boolean onTouch(View v, MotionEvent e) {
if (e.getAction() == MotionEvent.ACTION_DOWN) {
// SOME DOWN ACTIONS ...
} else if (e.getAction() == MotionEvent.ACTION_MOVE) {
// SOME MOVE ACTIONS ...
} else if (e.getAction() == MotionEvent.ACTION_UP) {
if (mLastMotionEventAction == MotionEvent.ACTION_DOWN){
// SOME TAP ACTIONS ...
}
}
mLastMotionEventAction = e.getAction();
return true;
}
Another option (for sensitive devices):
private long mLastDownEventTime = 0;
@Override
public boolean onTouch(View v, MotionEvent e) {
if (e.getAction() == MotionEvent.ACTION_DOWN) {
mLastDownEventTime = System.currentTimeMillis();
// SOME DOWN ACTIONS ...
} else if (e.getAction() == MotionEvent.ACTION_MOVE) {
// SOME MOVE ACTIONS ...
} else if (e.getAction() == MotionEvent.ACTION_UP) {
if (System.currentTimeMillis() - mLastDownEventTime < 500){
// SOME TAP ACTIONS ...
}
}
return true;
}
This will trigger tap action only if 200ms or less have passed since last down press. Of course, you can change the timing for best UX.
回答2:
You must return false
if you want to pass the event along to the Map as well. Otherwise, as you describe, the map will not react to touch gestures. This is because, returning true
means that you consumed the event.
回答3:
I know this is an old question, but the right way to do it is using getScaledTouchSlop()
which returns the distance in pixels a touch can wander before we think the user is scrolling.
Implement it like this in your onTouch method:
@Override
public boolean onTouch(final View v, MotionEvent event) {
int mSwipeSlop = ViewConfiguration.get(context).
getScaledTouchSlop();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// DO
break;
case MotionEvent.ACTION_CANCEL:
// DO
break;
case MotionEvent.ACTION_MOVE:
{
float x = event.getX() + v.getTranslationX();
float deltaX = x - mDownX;
float deltaXAbs = Math.abs(deltaX);
float y = event.getY() + v.getTranslationY();
float deltaY = Y - mDownY;
float deltaYAbs = Math.abs(deltaY);
float absDist = Math.sqrt(Math.pow(deltaXAbs, 2) + Math.pow(deltaXAbs, 2));
if (!mSwiping) {
if (absDist > mSwipeSlop) {
mSwiping = true;
}
}
break;
case MotionEvent.ACTION_UP:
{
if (mSwiping) {
// DO MOVE ACTIONS
}
else {
// DO TAP ACTIONS
}
}
break;
default:
return false;
}
return true;
};
developer page: http://developer.android.com/reference/android/view/ViewConfiguration.html#getScaledTouchSlop()
来源:https://stackoverflow.com/questions/12618045/how-to-make-ontouch-works-like-ontap-in-android