Better touch handling for doubletap scale.
This commit is contained in:
parent
66175e3ce8
commit
266c085fbd
1 changed files with 48 additions and 23 deletions
|
@ -13,21 +13,26 @@ import org.apache.commons.logging.Log;
|
|||
|
||||
public class DoubleTapScaleDetector {
|
||||
private static final Log LOG = PlatformUtil.getLog(DoubleTapScaleDetector.class);
|
||||
private static final int DOUBLE_TAPPING_DELTA = ViewConfiguration.getTapTimeout() + 100;
|
||||
private static final int DOUBLE_TAP_TIMEOUT = ViewConfiguration.getDoubleTapTimeout();
|
||||
private static final int DOUBLE_TAP_MIN_TIME = 40;
|
||||
private static final int DP_PER_1X = 200;
|
||||
|
||||
private final DoubleTapZoomListener listener;
|
||||
protected final Context ctx;
|
||||
|
||||
private long startTime = 0;
|
||||
private boolean isDoubleTapping = false;
|
||||
private float startX;
|
||||
private float startY;
|
||||
private float scale;
|
||||
private MotionEvent firstDown;
|
||||
private MotionEvent firstUp;
|
||||
private int mDoubleTapSlopSquare;
|
||||
|
||||
public DoubleTapScaleDetector(Context ctx, DoubleTapZoomListener listener) {
|
||||
this.ctx = ctx;
|
||||
this.listener = listener;
|
||||
|
||||
final ViewConfiguration configuration = ViewConfiguration.get(ctx);
|
||||
int doubleTapSlop = configuration.getScaledTouchSlop();
|
||||
mDoubleTapSlopSquare = doubleTapSlop * doubleTapSlop;
|
||||
}
|
||||
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
|
@ -41,26 +46,28 @@ public class DoubleTapScaleDetector {
|
|||
listener.onZoomEnded(scale, 0);
|
||||
return true;
|
||||
} else {
|
||||
startTime = currentTime;
|
||||
return true;
|
||||
firstUp = MotionEvent.obtain(event);
|
||||
}
|
||||
} else if (event.getAction() == MotionEvent.ACTION_DOWN && !isDoubleTapping
|
||||
&& currentTime - startTime < DOUBLE_TAPPING_DELTA) {
|
||||
} else {
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN && !isDoubleTapping) {
|
||||
if (isConsideredDoubleTap(firstDown, firstUp, event)) {
|
||||
isDoubleTapping = true;
|
||||
startX = event.getX();
|
||||
startY = event.getY();
|
||||
listener.onGestureInit(startX, startY, startX, startY);
|
||||
listener.onZoomStarted(new PointF(startX, startY));
|
||||
float x = event.getX();
|
||||
float y = event.getY();
|
||||
listener.onGestureInit(x, y, x, y);
|
||||
listener.onZoomStarted(new PointF(x, y));
|
||||
return true;
|
||||
} else {
|
||||
firstDown = MotionEvent.obtain(event);
|
||||
}
|
||||
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
|
||||
if (isDoubleTapping) {
|
||||
float delta = convertPxToDp((int) (startY - event.getY()));
|
||||
float delta = convertPxToDp((int) (firstDown.getY() - event.getY()));
|
||||
float scaleDelta = delta / DP_PER_1X;
|
||||
scale = 1 - scaleDelta;
|
||||
listener.onZoomingOrRotating(scale, 0);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -74,6 +81,24 @@ public class DoubleTapScaleDetector {
|
|||
return Math.round(px / (Resources.getSystem().getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));
|
||||
}
|
||||
|
||||
private final boolean isConsideredDoubleTap(MotionEvent firstDown,
|
||||
MotionEvent firstUp,
|
||||
MotionEvent secondDown) {
|
||||
if (firstDown == null || firstUp == null || secondDown == null) {
|
||||
return false;
|
||||
}
|
||||
final long deltaTime = secondDown.getEventTime() - firstUp.getEventTime();
|
||||
if (deltaTime > DOUBLE_TAP_TIMEOUT || deltaTime < DOUBLE_TAP_MIN_TIME) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int deltaX = (int) firstDown.getX() - (int) secondDown.getX();
|
||||
int deltaY = (int) firstDown.getY() - (int) secondDown.getY();
|
||||
int squared = deltaX * deltaX + deltaY * deltaY;
|
||||
boolean toReturn = squared < mDoubleTapSlopSquare;
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
public interface DoubleTapZoomListener {
|
||||
public void onZoomStarted(PointF centerPoint);
|
||||
|
||||
|
|
Loading…
Reference in a new issue