Skip to content

Commit

Permalink
Changed behaviour of pinch and quickzoom gestures as image reaches ed…
Browse files Browse the repository at this point in the history
…ge of screen for smoother zoom. Restructured debug.
  • Loading branch information
davemorrissey committed Nov 5, 2016
1 parent 41c5d10 commit 4505d63
Showing 1 changed file with 67 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -240,10 +240,11 @@ public class SubsamplingScaleImageView extends View {

// Current quickscale state
private final float quickScaleThreshold;
private PointF quickScaleCenter;
private float quickScaleLastDistance;
private PointF quickScaleLastPoint;
private boolean quickScaleMoved;
private PointF quickScaleVLastPoint;
private PointF quickScaleSCenter;
private PointF quickScaleVStart;

// Scale and center animation tracking
private Anim anim;
Expand Down Expand Up @@ -469,10 +470,11 @@ private void reset(boolean newImage) {
fullImageSampleSize = 0;
vCenterStart = null;
vDistStart = 0;
quickScaleCenter = null;
quickScaleLastDistance = 0f;
quickScaleLastPoint = null;
quickScaleMoved = false;
quickScaleSCenter = null;
quickScaleVLastPoint = null;
quickScaleVStart = null;
anim = null;
satTemp = null;
matrix = null;
Expand Down Expand Up @@ -552,9 +554,10 @@ public boolean onDoubleTap(MotionEvent e) {
scaleStart = scale;
isQuickScaling = true;
isZooming = true;
quickScaleCenter = viewToSourceCoord(vCenterStart);
quickScaleLastDistance = -1F;
quickScaleLastPoint = new PointF(quickScaleCenter.x, quickScaleCenter.y);
quickScaleSCenter = viewToSourceCoord(vCenterStart);
quickScaleVStart = new PointF(e.getX(), e.getY());
quickScaleVLastPoint = new PointF(quickScaleSCenter.x, quickScaleSCenter.y);
quickScaleMoved = false;
// We need to get events in onTouchEvent after this.
return false;
Expand Down Expand Up @@ -704,6 +707,7 @@ private boolean onTouchEventInternal(@NonNull MotionEvent event) {
isPanning = true;
consumed = true;

double previousScale = scale;
scale = Math.min(maxScale, (vDistEnd / vDistStart) * scaleStart);

if (scale <= minScale()) {
Expand All @@ -721,6 +725,13 @@ private boolean onTouchEventInternal(@NonNull MotionEvent event) {
float vTopNow = vTopStart * (scale/scaleStart);
vTranslate.x = vCenterEndX - vLeftNow;
vTranslate.y = vCenterEndY - vTopNow;
if ((previousScale * sHeight() < getHeight() && scale * sHeight() >= getHeight()) || (previousScale * sWidth() < getWidth() && scale * sWidth() >= getWidth())) {
fitToBounds(true);
vCenterStart.set(vCenterEndX, vCenterEndY);
vTranslateStart.set(vTranslate);
scaleStart = scale;
vDistStart = vDistEnd;
}
} else if (sRequestedCenter != null) {
// With a center specified from code, zoom around that point.
vTranslate.x = (getWidth()/2) - (scale * sRequestedCenter.x);
Expand All @@ -737,13 +748,15 @@ private boolean onTouchEventInternal(@NonNull MotionEvent event) {
} else if (isQuickScaling) {
// One finger zoom
// Stole Google's Magical Formula™ to make sure it feels the exact same
float dist = Math.abs(vCenterStart.y - event.getY()) * 2 + quickScaleThreshold;
float dist = Math.abs(quickScaleVStart.y - event.getY()) * 2 + quickScaleThreshold;

if (quickScaleLastDistance == -1F) quickScaleLastDistance = dist;
boolean isUpwards = event.getY() > quickScaleLastPoint.y;
quickScaleLastPoint.set(0, event.getY());
if (quickScaleLastDistance == -1f) {
quickScaleLastDistance = dist;
}
boolean isUpwards = event.getY() > quickScaleVLastPoint.y;
quickScaleVLastPoint.set(0, event.getY());

float spanDiff = (Math.abs(1 - (dist / quickScaleLastDistance)) * 0.5F);
float spanDiff = Math.abs(1 - (dist / quickScaleLastDistance)) * 0.5f;

if (spanDiff > 0.03f || quickScaleMoved) {
quickScaleMoved = true;
Expand All @@ -753,6 +766,7 @@ private boolean onTouchEventInternal(@NonNull MotionEvent event) {
multiplier = isUpwards ? (1 + spanDiff) : (1 - spanDiff);
}

double previousScale = scale;
scale = Math.max(minScale(), Math.min(maxScale, scale * multiplier));

if (panEnabled) {
Expand All @@ -762,6 +776,13 @@ private boolean onTouchEventInternal(@NonNull MotionEvent event) {
float vTopNow = vTopStart * (scale/scaleStart);
vTranslate.x = vCenterStart.x - vLeftNow;
vTranslate.y = vCenterStart.y - vTopNow;
if ((previousScale * sHeight() < getHeight() && scale * sHeight() >= getHeight()) || (previousScale * sWidth() < getWidth() && scale * sWidth() >= getWidth())) {
fitToBounds(true);
vCenterStart.set(sourceToViewCoord(quickScaleSCenter));
vTranslateStart.set(vTranslate);
scaleStart = scale;
dist = 0;
}
} else if (sRequestedCenter != null) {
// With a center specified from code, zoom around that point.
vTranslate.x = (getWidth()/2) - (scale * sRequestedCenter.x);
Expand Down Expand Up @@ -830,7 +851,7 @@ private boolean onTouchEventInternal(@NonNull MotionEvent event) {
if (isQuickScaling) {
isQuickScaling = false;
if (!quickScaleMoved) {
doubleTapZoom(quickScaleCenter, vCenterStart);
doubleTapZoom(quickScaleSCenter, vCenterStart);
}
}
if (maxTouchCount > 0 && (isZooming || isPanning)) {
Expand Down Expand Up @@ -1021,23 +1042,6 @@ protected void onDraw(Canvas canvas) {
}
}

if (debug) {
canvas.drawText("Scale: " + String.format(Locale.ENGLISH, "%.2f", scale), 5, 15, debugPaint);
canvas.drawText("Translate: " + String.format(Locale.ENGLISH, "%.2f", vTranslate.x) + ":" + String.format(Locale.ENGLISH, "%.2f", vTranslate.y), 5, 35, debugPaint);
PointF center = getCenter();
canvas.drawText("Source center: " + String.format(Locale.ENGLISH, "%.2f", center.x) + ":" + String.format(Locale.ENGLISH, "%.2f", center.y), 5, 55, debugPaint);

if (anim != null) {
PointF vCenterStart = sourceToViewCoord(anim.sCenterStart);
PointF vCenterEndRequested = sourceToViewCoord(anim.sCenterEndRequested);
PointF vCenterEnd = sourceToViewCoord(anim.sCenterEnd);
canvas.drawCircle(vCenterStart.x, vCenterStart.y, 10, debugPaint);
canvas.drawCircle(vCenterEndRequested.x, vCenterEndRequested.y, 20, debugPaint);
canvas.drawCircle(vCenterEnd.x, vCenterEnd.y, 25, debugPaint);
canvas.drawCircle(getWidth() / 2, getHeight() / 2, 30, debugPaint);
}
}

} else if (bitmap != null) {

float xScale = scale, yScale = scale;
Expand Down Expand Up @@ -1069,6 +1073,40 @@ protected void onDraw(Canvas canvas) {
canvas.drawBitmap(bitmap, matrix, bitmapPaint);

}

if (debug) {
canvas.drawText("Scale: " + String.format(Locale.ENGLISH, "%.2f", scale), 5, 15, debugPaint);
canvas.drawText("Translate: " + String.format(Locale.ENGLISH, "%.2f", vTranslate.x) + ":" + String.format(Locale.ENGLISH, "%.2f", vTranslate.y), 5, 35, debugPaint);
PointF center = getCenter();
canvas.drawText("Source center: " + String.format(Locale.ENGLISH, "%.2f", center.x) + ":" + String.format(Locale.ENGLISH, "%.2f", center.y), 5, 55, debugPaint);
debugPaint.setStrokeWidth(2f);
if (anim != null) {
PointF vCenterStart = sourceToViewCoord(anim.sCenterStart);
PointF vCenterEndRequested = sourceToViewCoord(anim.sCenterEndRequested);
PointF vCenterEnd = sourceToViewCoord(anim.sCenterEnd);
canvas.drawCircle(vCenterStart.x, vCenterStart.y, 10, debugPaint);
debugPaint.setColor(Color.RED);
canvas.drawCircle(vCenterEndRequested.x, vCenterEndRequested.y, 20, debugPaint);
debugPaint.setColor(Color.BLUE);
canvas.drawCircle(vCenterEnd.x, vCenterEnd.y, 25, debugPaint);
debugPaint.setColor(Color.CYAN);
canvas.drawCircle(getWidth() / 2, getHeight() / 2, 30, debugPaint);
}
if (vCenterStart != null) {
debugPaint.setColor(Color.RED);
canvas.drawCircle(vCenterStart.x, vCenterStart.y, 20, debugPaint);
}
if (quickScaleSCenter != null) {
debugPaint.setColor(Color.BLUE);
canvas.drawCircle(sourceToViewX(quickScaleSCenter.x), sourceToViewY(quickScaleSCenter.y), 35, debugPaint);
}
if (quickScaleVStart != null) {
debugPaint.setColor(Color.CYAN);
canvas.drawCircle(quickScaleVStart.x, quickScaleVStart.y, 30, debugPaint);
}
debugPaint.setColor(Color.MAGENTA);
debugPaint.setStrokeWidth(1f);
}
}

/**
Expand Down

0 comments on commit 4505d63

Please sign in to comment.