summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkhoaha <khoaha93@gmail.com>2014-10-17 15:23:44 -0400
committerAndrew Sapperstein <asapperstein@google.com>2014-10-17 12:28:07 -0700
commit0667dbcdae03086a7beedd47c68d098441f7fedc (patch)
treef740022aa454073ab3f304832633df34c1c67027
parent1d616c2b1a3012f398432204875a0efd6f6d68d7 (diff)
downloadphotoviewer-0667dbcdae03086a7beedd47c68d098441f7fedc.tar.gz
Overzoom animation added when attempting to zoom past max scale.
For consistency, the user can scale a small amount beyond the maximum scale and the image is zoomed out to the maximum scale upon release. Also fixed bug where panning during a zoom out may result in bad centering. Change-Id: Ic5edb22d87e8f761c8c87224ba0dcd34bb9084c4
-rw-r--r--src/com/android/ex/photo/views/PhotoView.java43
1 files changed, 38 insertions, 5 deletions
diff --git a/src/com/android/ex/photo/views/PhotoView.java b/src/com/android/ex/photo/views/PhotoView.java
index ff55eaa..b87f6a1 100644
--- a/src/com/android/ex/photo/views/PhotoView.java
+++ b/src/com/android/ex/photo/views/PhotoView.java
@@ -63,6 +63,8 @@ public class PhotoView extends View implements OnGestureListener,
private static final long SNAP_DELAY = 250L;
/** By how much to scale the image when double click occurs */
private final static float DOUBLE_TAP_SCALE_FACTOR = 2.0f;
+ /** Amount which can be zoomed in past the maximum scale, and then scaled back */
+ private final static float SCALE_OVERZOOM_FACTOR = 1.5f;
/** Amount of translation needed before starting a snap animation */
private final static float SNAP_THRESHOLD = 20.0f;
/** The width & height of the bitmap returned by {@link #getCroppedPhoto()} */
@@ -339,7 +341,7 @@ public class PhotoView extends View implements OnGestureListener,
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
- if (mTransformsEnabled) {
+ if (mTransformsEnabled && !mScaleRunnable.mRunning) {
translate(-distanceX, -distanceY);
}
return true;
@@ -356,7 +358,7 @@ public class PhotoView extends View implements OnGestureListener,
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
- if (mTransformsEnabled) {
+ if (mTransformsEnabled && !mScaleRunnable.mRunning) {
mTranslateRunnable.start(velocityX, velocityY);
}
return true;
@@ -384,6 +386,37 @@ public class PhotoView extends View implements OnGestureListener,
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
+ // Scale back to the maximum if over-zoomed
+ float currentScale = getScale();
+ if (currentScale > mMaxScale) {
+ // The number of times the crop amount pulled in can fit on the screen
+ float marginFit = 1 / (1 - mMaxScale / currentScale);
+ // The (negative) relative maximum distance from an image edge such that when scaled
+ // this far from the edge, all of the image off-screen in that direction is pulled in
+ float relativeDistance = 1 - marginFit;
+ float centerX = getWidth() / 2;
+ float centerY = getHeight() / 2;
+ // This center will pull all of the margin from the lesser side, over will expose trim
+ float maxX = mTranslateRect.left * relativeDistance;
+ float maxY = mTranslateRect.top * relativeDistance;
+ // This center will pull all of the margin from the greater side, over will expose trim
+ float minX = getWidth() * marginFit + mTranslateRect.right * relativeDistance;
+ float minY = getHeight() * marginFit + mTranslateRect.bottom * relativeDistance;
+ // Adjust center according to bounds to avoid bad crop
+ if (minX > maxX) {
+ // Border is inevitable due to small image size, so we split the crop difference
+ centerX = (minX + maxX) / 2;
+ } else {
+ centerX = Math.min(Math.max(minX, centerX), maxX);
+ }
+ if (minY > maxY) {
+ // Border is inevitable due to small image size, so we split the crop difference
+ centerY = (minY + maxY) / 2;
+ } else {
+ centerY = Math.min(Math.max(minY, centerY), maxY);
+ }
+ mScaleRunnable.start(currentScale, mMaxScale, centerX, centerY);
+ }
if (mTransformsEnabled && mIsDoubleTouch) {
mDoubleTapDebounce = true;
resetTransformations();
@@ -874,7 +907,7 @@ public class PhotoView extends View implements OnGestureListener,
} else {
mMinScale = getScale();
}
- mMaxScale = Math.max(mMinScale * 8, 8);
+ mMaxScale = Math.max(mMinScale * 4, 4);
}
/**
@@ -910,9 +943,9 @@ public class PhotoView extends View implements OnGestureListener,
// rotate back to the original orientation
mMatrix.postRotate(-mRotation, getWidth() / 2, getHeight() / 2);
- // ensure that mMixScale <= newScale <= mMaxScale
+ // ensure that mMinScale <= newScale <= mMaxScale
newScale = Math.max(newScale, mMinScale);
- newScale = Math.min(newScale, mMaxScale);
+ newScale = Math.min(newScale, mMaxScale * SCALE_OVERZOOM_FACTOR);
float currentScale = getScale();
float factor = newScale / currentScale;