summaryrefslogtreecommitdiff
path: root/org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/ImageViewTouch.java
diff options
context:
space:
mode:
authorAndrew Dolgov <[email protected]>2014-10-16 23:34:20 +0400
committerAndrew Dolgov <[email protected]>2014-10-16 23:34:20 +0400
commit124f869faae3a0f75a3825e6a8e195c17f3c626a (patch)
tree4a6f120195b60673994cfd78b6d0002bd1020bea /org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/ImageViewTouch.java
parentbc10c74406c0e8a16c40dbfcd30a138d441dd859 (diff)
initial for idea
Diffstat (limited to 'org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/ImageViewTouch.java')
-rw-r--r--org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/ImageViewTouch.java268
1 files changed, 268 insertions, 0 deletions
diff --git a/org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/ImageViewTouch.java b/org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/ImageViewTouch.java
new file mode 100644
index 0000000..73392b1
--- /dev/null
+++ b/org.fox.ttcomics/src/main/java/it/sephiroth/android/library/imagezoom/ImageViewTouch.java
@@ -0,0 +1,268 @@
+package it.sephiroth.android.library.imagezoom;
+
+import android.content.Context;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.GestureDetector;
+import android.view.GestureDetector.OnGestureListener;
+import android.view.MotionEvent;
+import android.view.ScaleGestureDetector;
+import android.view.ScaleGestureDetector.OnScaleGestureListener;
+import android.view.ViewConfiguration;
+
+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;
+ protected int mTouchSlop;
+ protected float mCurrentScaleFactor;
+ protected float mScaleFactor;
+ protected int mDoubleTapDirection;
+ protected OnGestureListener mGestureListener;
+ protected OnScaleGestureListener mScaleListener;
+ protected boolean mDoubleTapToZoomEnabled = true;
+ protected boolean mScaleEnabled = true;
+ protected boolean mScrollEnabled = true;
+
+ private OnImageViewTouchDoubleTapListener doubleTapListener;
+
+ public interface OnScaleChangedListener {
+ public void onScaleChanged(float scale);
+ }
+
+ protected OnScaleChangedListener mScaleChangedListener;
+
+ public ImageViewTouch( Context context, AttributeSet attrs ) {
+ super( context, attrs );
+ }
+
+ @Override
+ protected void init() {
+ super.init();
+ mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
+ mGestureListener = getGestureListener();
+ mScaleListener = getScaleListener();
+
+ mScaleDetector = new ScaleGestureDetector( getContext(), mScaleListener );
+ mGestureDetector = new GestureDetector( getContext(), mGestureListener, null, true );
+
+ mCurrentScaleFactor = 1f;
+ mDoubleTapDirection = 1;
+ }
+
+ public void setDoubleTapListener( OnImageViewTouchDoubleTapListener doubleTapListener ){
+ this.doubleTapListener = doubleTapListener;
+ }
+
+ public void setDoubleTapToZoomEnabled( boolean value ) {
+ mDoubleTapToZoomEnabled = value;
+ }
+
+ public void setScaleEnabled( boolean value ) {
+ mScaleEnabled = value;
+ }
+
+ public void setScrollEnabled( boolean value ) {
+ mScrollEnabled = value;
+ }
+
+ public boolean getDoubleTapEnabled() {
+ return mDoubleTapToZoomEnabled;
+ }
+
+ protected OnGestureListener getGestureListener() {
+ return new GestureListener();
+ }
+
+ protected OnScaleGestureListener getScaleListener() {
+ return new ScaleListener();
+ }
+
+ @Override
+ protected void onBitmapChanged( Drawable drawable ) {
+ super.onBitmapChanged( drawable );
+
+ float v[] = new float[9];
+ mSuppMatrix.getValues( v );
+ mCurrentScaleFactor = v[Matrix.MSCALE_X];
+ }
+
+ @Override
+ protected void _setImageDrawable( final Drawable drawable, final boolean reset, final Matrix initial_matrix, final float maxZoom ) {
+ super._setImageDrawable( drawable, reset, initial_matrix, maxZoom );
+ mScaleFactor = getMaxZoom() / 3;
+ }
+
+ @Override
+ public boolean onTouchEvent( MotionEvent event ) {
+ mScaleDetector.onTouchEvent( event );
+ if ( !mScaleDetector.isInProgress() ) mGestureDetector.onTouchEvent( event );
+ int action = event.getAction();
+ switch ( action & MotionEvent.ACTION_MASK ) {
+ case MotionEvent.ACTION_UP:
+ if ( getScale() < 1f ) {
+ zoomTo( 1f, 50 );
+ }
+ break;
+ }
+ return true;
+ }
+
+ @Override
+ protected void onZoom( float scale ) {
+ super.onZoom( scale );
+ if ( !mScaleDetector.isInProgress() ) mCurrentScaleFactor = scale;
+
+ if (mScaleChangedListener != null) {
+ mScaleChangedListener.onScaleChanged(mCurrentScaleFactor);
+ }
+ }
+
+ protected float onDoubleTapPost( float scale, float maxZoom ) {
+ if ( mDoubleTapDirection == 1 ) {
+ if (mCurrentScaleFactor - 1.0f < 0.01) { //( scale + ( mScaleFactor * 2 ) ) <= maxZoom
+
+ float scaleFactor = mScaleFactor;
+
+ RectF bitmapRect = getBitmapRect();
+
+ float w = bitmapRect.right - bitmapRect.left;
+ float h = bitmapRect.bottom - bitmapRect.top;
+
+ if (w < getWidth()) {
+ scaleFactor = (float)getWidth() / w - scale;
+ } else if (h < getHeight()) {
+ scaleFactor = (float)getHeight() / h - scale;
+ }
+
+ return scale + scaleFactor;
+ } else {
+ mDoubleTapDirection = -1;
+ return maxZoom;
+ }
+ } else {
+ mDoubleTapDirection = 1;
+ 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
+ public boolean onDoubleTap( MotionEvent e ) {
+ Log.i( LOG_TAG, "onDoubleTap. double tap enabled? " + mDoubleTapToZoomEnabled);
+ if (mDoubleTapToZoomEnabled) {
+ float scale = getScale();
+ float targetScale = scale;
+ targetScale = onDoubleTapPost( scale, getMaxZoom() );
+ targetScale = Math.min( getMaxZoom(), Math.max( targetScale, MIN_ZOOM ) );
+ mCurrentScaleFactor = targetScale;
+ zoomTo( targetScale, e.getX(), e.getY(), 200 );
+ invalidate();
+ }
+
+ if( null != doubleTapListener ){
+ doubleTapListener.onDoubleTap();
+ }
+
+ return super.onDoubleTap( e );
+ }
+
+ @Override
+ public void onLongPress( MotionEvent e ) {
+ if ( isLongClickable() ) {
+ if ( !mScaleDetector.isInProgress() ) {
+ setPressed( true );
+ performLongClick();
+ }
+ }
+ }
+
+ @Override
+ public boolean onScroll( MotionEvent e1, MotionEvent e2, float distanceX, float distanceY ) {
+ if ( !mScrollEnabled ) return false;
+
+ if ( e1 == null || e2 == null ) return false;
+ if ( e1.getPointerCount() > 1 || e2.getPointerCount() > 1 ) return false;
+ if ( mScaleDetector.isInProgress() ) return false;
+ if ( getScale() == 1f ) return false;
+ scrollBy( -distanceX, -distanceY );
+ invalidate();
+ return super.onScroll( e1, e2, distanceX, distanceY );
+ }
+
+ @Override
+ public boolean onFling( MotionEvent e1, MotionEvent e2, float velocityX, float velocityY ) {
+ if ( !mScrollEnabled ) return false;
+
+ if ( e1.getPointerCount() > 1 || e2.getPointerCount() > 1 ) return false;
+ if ( mScaleDetector.isInProgress() ) return false;
+
+ float diffX = e2.getX() - e1.getX();
+ float diffY = e2.getY() - e1.getY();
+
+ if ( Math.abs( velocityX ) > 800 || Math.abs( velocityY ) > 800 ) {
+ scrollBy( diffX / 2, diffY / 2, 300 );
+ invalidate();
+ }
+ return super.onFling( e1, e2, velocityX, velocityY );
+ }
+ }
+
+ public class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
+
+ @SuppressWarnings("unused")
+ @Override
+ public boolean onScale( ScaleGestureDetector detector ) {
+ float span = detector.getCurrentSpan() - detector.getPreviousSpan();
+ float targetScale = mCurrentScaleFactor * detector.getScaleFactor();
+ if ( mScaleEnabled ) {
+ targetScale = Math.min( getMaxZoom(), Math.max( targetScale, MIN_ZOOM ) );
+ zoomTo( targetScale, detector.getFocusX(), detector.getFocusY() );
+ mCurrentScaleFactor = Math.min( getMaxZoom(), Math.max( targetScale, MIN_ZOOM ) );
+ mDoubleTapDirection = 1;
+ invalidate();
+ return true;
+ }
+ return false;
+ }
+ }
+
+ public interface OnImageViewTouchDoubleTapListener {
+ void onDoubleTap();
+ }
+
+ public void setOnScaleChangedListener(OnScaleChangedListener listener) {
+ mScaleChangedListener = listener;
+ }
+}