From 9177b96e3b6e4c31e187dd3f2655fc1ae010aa2c Mon Sep 17 00:00:00 2001 From: Jesse Rosalia Date: Sun, 7 Oct 2012 21:58:53 -0400 Subject: [PATCH 1/2] Added centerOn method --- .../library/imagezoom/ImageViewTouch.java | 4 +- .../library/imagezoom/ImageViewTouchBase.java | 96 +++++++++++++++---- 2 files changed, 78 insertions(+), 22 deletions(-) diff --git a/ImageViewTouch/src/it/sephiroth/android/library/imagezoom/ImageViewTouch.java b/ImageViewTouch/src/it/sephiroth/android/library/imagezoom/ImageViewTouch.java index 1abdcb6..563ee73 100644 --- a/ImageViewTouch/src/it/sephiroth/android/library/imagezoom/ImageViewTouch.java +++ b/ImageViewTouch/src/it/sephiroth/android/library/imagezoom/ImageViewTouch.java @@ -163,7 +163,7 @@ public boolean onDoubleTap( MotionEvent e ) { targetScale = onDoubleTapPost( scale, getMaxZoom() ); targetScale = Math.min( getMaxZoom(), Math.max( targetScale, MIN_ZOOM ) ); mCurrentScaleFactor = targetScale; - zoomTo( targetScale, e.getX(), e.getY(), 200 ); + doZoomTo( targetScale, e.getX(), e.getY(), 200 ); invalidate(); } @@ -224,7 +224,7 @@ public boolean onScale( ScaleGestureDetector detector ) { float targetScale = mCurrentScaleFactor * detector.getScaleFactor(); if ( mScaleEnabled ) { targetScale = Math.min( getMaxZoom(), Math.max( targetScale, MIN_ZOOM ) ); - zoomTo( targetScale, detector.getFocusX(), detector.getFocusY() ); + doZoomTo( targetScale, detector.getFocusX(), detector.getFocusY() ); mCurrentScaleFactor = Math.min( getMaxZoom(), Math.max( targetScale, MIN_ZOOM ) ); mDoubleTapDirection = 1; invalidate(); diff --git a/ImageViewTouch/src/it/sephiroth/android/library/imagezoom/ImageViewTouchBase.java b/ImageViewTouch/src/it/sephiroth/android/library/imagezoom/ImageViewTouchBase.java index a0e1a3b..199627c 100644 --- a/ImageViewTouch/src/it/sephiroth/android/library/imagezoom/ImageViewTouchBase.java +++ b/ImageViewTouch/src/it/sephiroth/android/library/imagezoom/ImageViewTouchBase.java @@ -226,7 +226,23 @@ protected float maxZoom() { float fw = (float) drawable.getIntrinsicWidth() / (float) mThisWidth; float fh = (float) drawable.getIntrinsicHeight() / (float) mThisHeight; - float max = Math.max( fw, fh ) * 4; + +// float lim, oth; +// if (fw < fh) { +// lim = fw; +// oth = fh; +// } else { +// lim = fh; +// oth = fw; +// } +// +// oth = oth * (1.0f/lim); +//// float lim = Math.min() +//// if (fh < 1) { +//// fw = fw * (1.0f/fh); +//// fh = 1.0f; +//// } + float max = (1.0f / Math.min( fw, fh )) * 4; return max; } @@ -381,16 +397,27 @@ protected void postScale( float scale, float centerX, float centerY ) { protected void zoomTo( float scale ) { float cx = getWidth() / 2F; float cy = getHeight() / 2F; - zoomTo( scale, cx, cy ); + doZoomTo( scale, cx, cy ); } public void zoomTo( float scale, float durationMs ) { float cx = getWidth() / 2F; float cy = getHeight() / 2F; - zoomTo( scale, cx, cy, durationMs ); + doZoomTo(scale, cx, cy, durationMs); +// doZoomTo( scale, cx, cy, durationMs ); } - protected void zoomTo( float scale, float centerX, float centerY ) { + public void zoomTo( float scale, float imageCx, float imageCy, float durationMs ) { + zoomTo( scale, durationMs ); + Matrix m = getImageViewMatrix(); +// mBitmapRect.set( 0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight() ); + float[] pt = new float[] {imageCx, imageCy}; + m.mapPoints(pt); + + panBy(pt[1], pt[0]); + } + + protected void doZoomTo( float scale, float centerX, float centerY ) { // Log.i(LOG_TAG, "zoomTo"); if ( scale > mMaxZoom ) scale = mMaxZoom; @@ -403,6 +430,31 @@ protected void zoomTo( float scale, float centerX, float centerY ) { protected void onZoom( float scale ) {} + /** + * Center on a specific coordinate in the image. + * + * This method uses image-based coordinates, with 0,0 at the top left of the image. It is scale agnostic. + * + */ + public void centerOn( float x, float y ) { + Drawable d = getDrawable(); + if (d == null) { + return; //nothing to do + } + //get the bitmap rect, which represents the rectangle of the view at the specified scale + //NOTE: this currently has no relation to the actual bitmap...we will provide that relation in this method + RectF rect = getBitmapRect(); + //determine the centerX and centerY of the bitmap rect + float viewCenterX = (rect.right - rect.left)/2; + float viewCenterY = (rect.bottom - rect.top)/2; + + //NOTE: postTranslate expects - numbers to pull the image right and + to pull it left + float xp = viewCenterX - (x / d.getIntrinsicWidth()) * (rect.right - rect.left); //-rect.left - (x * viewCenterX / imageCenterX); + //NOTE: postTranslate expects - numbers to pull the image down, and + to pull it up + float yp = viewCenterY - (y / d.getIntrinsicHeight()) * (rect.bottom - rect.top); //yp = rect.top + (y * viewCenterY / imageCenterY); + postTranslate(xp, yp); + } + public void scrollBy( float x, float y ) { panBy( x, y ); } @@ -457,26 +509,30 @@ public void run() { } ); } - protected void zoomTo( float scale, final float centerX, final float centerY, final float durationMs ) { + protected void doZoomTo( float scale, final float centerX, final float centerY, final float durationMs ) { // Log.i( LOG_TAG, "zoomTo: " + scale + ", " + centerX + ": " + centerY ); final long startTime = System.currentTimeMillis(); final float incrementPerMs = ( scale - getScale() ) / durationMs; final float oldScale = getScale(); - mHandler.post( new Runnable() { - - @Override - public void run() { - long now = System.currentTimeMillis(); - float currentMs = Math.min( durationMs, now - startTime ); - float target = oldScale + ( incrementPerMs * currentMs ); - zoomTo( target, centerX, centerY ); - if ( currentMs < durationMs ) { - mHandler.post( this ); - } else { - // if ( getScale() < 1f ) {} - } - } - } ); + if (durationMs == 0) { + doZoomTo(scale, centerX, centerY); + } else { + mHandler.post( new Runnable() { + + @Override + public void run() { + long now = System.currentTimeMillis(); + float currentMs = Math.min( durationMs, now - startTime ); + float target = oldScale + ( incrementPerMs * currentMs ); + doZoomTo( target, centerX, centerY ); + if ( currentMs < durationMs ) { + mHandler.post( this ); + } else { + // if ( getScale() < 1f ) {} + } + } + } ); + } } @Override From 75c17d4c522ddb6eb462b6458d8e9221cd8e32fa Mon Sep 17 00:00:00 2001 From: Jesse Rosalia Date: Sun, 20 Jan 2013 00:48:52 -0500 Subject: [PATCH 2/2] Removed superfluous changes, name changes, commented code, etc. --- .../library/imagezoom/ImageViewTouch.java | 31 ++--------- .../library/imagezoom/ImageViewTouchBase.java | 51 +++++-------------- 2 files changed, 17 insertions(+), 65 deletions(-) diff --git a/ImageViewTouch/src/it/sephiroth/android/library/imagezoom/ImageViewTouch.java b/ImageViewTouch/src/it/sephiroth/android/library/imagezoom/ImageViewTouch.java index 563ee73..367a8c1 100644 --- a/ImageViewTouch/src/it/sephiroth/android/library/imagezoom/ImageViewTouch.java +++ b/ImageViewTouch/src/it/sephiroth/android/library/imagezoom/ImageViewTouch.java @@ -16,7 +16,6 @@ public class ImageViewTouch extends ImageViewTouchBase { - private static final float SCROLL_DELTA_THRESHOLD = 1.0f; static final float MIN_ZOOM = 0.9f; protected ScaleGestureDetector mScaleDetector; protected GestureDetector mGestureDetector; @@ -127,31 +126,7 @@ protected float onDoubleTapPost( float scale, float maxZoom ) { return 1f; } } - - /** - * Determines whether this ImageViewTouch can be scrolled. - * @param direction - * - positive direction value means scroll from right to left, - * negative value means scroll from left to right - * - * @return true if there is some more place to scroll, false - otherwise. - */ - public boolean canScroll(int direction) { - RectF bitmapRect = getBitmapRect(); - updateRect(bitmapRect, mScrollRect); - Rect imageViewRect = new Rect(); - getGlobalVisibleRect(imageViewRect); - - if (bitmapRect.right >= imageViewRect.right) { - if (direction < 0) { - return Math.abs(bitmapRect.right - imageViewRect.right) > SCROLL_DELTA_THRESHOLD; - } - } - - double bitmapScrollRectDelta = Math.abs(bitmapRect.left - mScrollRect.left); - return bitmapScrollRectDelta > SCROLL_DELTA_THRESHOLD; - } - + public class GestureListener extends GestureDetector.SimpleOnGestureListener { @Override @@ -163,7 +138,7 @@ public boolean onDoubleTap( MotionEvent e ) { targetScale = onDoubleTapPost( scale, getMaxZoom() ); targetScale = Math.min( getMaxZoom(), Math.max( targetScale, MIN_ZOOM ) ); mCurrentScaleFactor = targetScale; - doZoomTo( targetScale, e.getX(), e.getY(), 200 ); + zoomTo( targetScale, e.getX(), e.getY(), 200 ); invalidate(); } @@ -224,7 +199,7 @@ public boolean onScale( ScaleGestureDetector detector ) { float targetScale = mCurrentScaleFactor * detector.getScaleFactor(); if ( mScaleEnabled ) { targetScale = Math.min( getMaxZoom(), Math.max( targetScale, MIN_ZOOM ) ); - doZoomTo( targetScale, detector.getFocusX(), detector.getFocusY() ); + zoomTo( targetScale, detector.getFocusX(), detector.getFocusY() ); mCurrentScaleFactor = Math.min( getMaxZoom(), Math.max( targetScale, MIN_ZOOM ) ); mDoubleTapDirection = 1; invalidate(); diff --git a/ImageViewTouch/src/it/sephiroth/android/library/imagezoom/ImageViewTouchBase.java b/ImageViewTouch/src/it/sephiroth/android/library/imagezoom/ImageViewTouchBase.java index 199627c..f10af90 100644 --- a/ImageViewTouch/src/it/sephiroth/android/library/imagezoom/ImageViewTouchBase.java +++ b/ImageViewTouch/src/it/sephiroth/android/library/imagezoom/ImageViewTouchBase.java @@ -227,21 +227,6 @@ protected float maxZoom() { float fw = (float) drawable.getIntrinsicWidth() / (float) mThisWidth; float fh = (float) drawable.getIntrinsicHeight() / (float) mThisHeight; -// float lim, oth; -// if (fw < fh) { -// lim = fw; -// oth = fh; -// } else { -// lim = fh; -// oth = fw; -// } -// -// oth = oth * (1.0f/lim); -//// float lim = Math.min() -//// if (fh < 1) { -//// fw = fw * (1.0f/fh); -//// fh = 1.0f; -//// } float max = (1.0f / Math.min( fw, fh )) * 4; return max; } @@ -397,27 +382,16 @@ protected void postScale( float scale, float centerX, float centerY ) { protected void zoomTo( float scale ) { float cx = getWidth() / 2F; float cy = getHeight() / 2F; - doZoomTo( scale, cx, cy ); + zoomTo( scale, cx, cy ); } public void zoomTo( float scale, float durationMs ) { float cx = getWidth() / 2F; float cy = getHeight() / 2F; - doZoomTo(scale, cx, cy, durationMs); -// doZoomTo( scale, cx, cy, durationMs ); + zoomTo( scale, cx, cy, durationMs ); } - public void zoomTo( float scale, float imageCx, float imageCy, float durationMs ) { - zoomTo( scale, durationMs ); - Matrix m = getImageViewMatrix(); -// mBitmapRect.set( 0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight() ); - float[] pt = new float[] {imageCx, imageCy}; - m.mapPoints(pt); - - panBy(pt[1], pt[0]); - } - - protected void doZoomTo( float scale, float centerX, float centerY ) { + protected void zoomTo( float scale, float centerX, float centerY ) { // Log.i(LOG_TAG, "zoomTo"); if ( scale > mMaxZoom ) scale = mMaxZoom; @@ -444,14 +418,16 @@ public void centerOn( float x, float y ) { //get the bitmap rect, which represents the rectangle of the view at the specified scale //NOTE: this currently has no relation to the actual bitmap...we will provide that relation in this method RectF rect = getBitmapRect(); - //determine the centerX and centerY of the bitmap rect - float viewCenterX = (rect.right - rect.left)/2; - float viewCenterY = (rect.bottom - rect.top)/2; + float screenMidX = getWidth() / 2; + float screenMidY = getHeight() / 2; + //determine the centerX and centerY of the image on screen (these coordinates are scaled image coordinates) + float viewCenterX = -(rect.left - screenMidX); + float viewCenterY = -(rect.top - screenMidY); //NOTE: postTranslate expects - numbers to pull the image right and + to pull it left - float xp = viewCenterX - (x / d.getIntrinsicWidth()) * (rect.right - rect.left); //-rect.left - (x * viewCenterX / imageCenterX); + float xp = viewCenterX - (x / d.getIntrinsicWidth()) * (rect.right - rect.left); //NOTE: postTranslate expects - numbers to pull the image down, and + to pull it up - float yp = viewCenterY - (y / d.getIntrinsicHeight()) * (rect.bottom - rect.top); //yp = rect.top + (y * viewCenterY / imageCenterY); + float yp = viewCenterY - (y / d.getIntrinsicHeight()) * (rect.bottom - rect.top); postTranslate(xp, yp); } @@ -509,13 +485,14 @@ public void run() { } ); } - protected void doZoomTo( float scale, final float centerX, final float centerY, final float durationMs ) { + protected void zoomTo( float scale, final float centerX, final float centerY, final float durationMs ) { // Log.i( LOG_TAG, "zoomTo: " + scale + ", " + centerX + ": " + centerY ); final long startTime = System.currentTimeMillis(); final float incrementPerMs = ( scale - getScale() ) / durationMs; final float oldScale = getScale(); if (durationMs == 0) { - doZoomTo(scale, centerX, centerY); + //special case for instantaneous zoom + zoomTo(scale, centerX, centerY); } else { mHandler.post( new Runnable() { @@ -524,7 +501,7 @@ public void run() { long now = System.currentTimeMillis(); float currentMs = Math.min( durationMs, now - startTime ); float target = oldScale + ( incrementPerMs * currentMs ); - doZoomTo( target, centerX, centerY ); + zoomTo( target, centerX, centerY ); if ( currentMs < durationMs ) { mHandler.post( this ); } else {