diff options
author | khoaha <khoaha93@gmail.com> | 2014-10-17 15:23:44 -0400 |
---|---|---|
committer | khoaha <khoaha93@gmail.com> | 2014-10-17 15:23:44 -0400 |
commit | c9d25c87e10cc773f167b60a3d7b4b05f0c819ec (patch) | |
tree | 6a3e36a98d61511b50f38064e209d110790c8591 | |
parent | 656e80363682740f0344f9ec798e0d0d596d757a (diff) | |
download | photoviewer-c9d25c87e10cc773f167b60a3d7b4b05f0c819ec.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.java | 43 |
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 1792115..3fb1da3 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; |