package com.echo5bravo.govre.UTILS.ImageZoom; import android.content.Context; import android.util.AttributeSet; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.ScaleGestureDetector; import android.view.ViewConfiguration; public class ImageViewTouch extends ImageViewTouchBase { 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 GestureListener mGestureListener; protected ScaleListener mScaleListener; public ImageViewTouch( Context context, AttributeSet attrs ) { super( context, attrs ); } @Override protected void init() { super.init(); mTouchSlop = ViewConfiguration.getTouchSlop(); mGestureListener = new GestureListener(); mScaleListener = new ScaleListener(); mScaleDetector = new ScaleGestureDetector( getContext(), mScaleListener ); mGestureDetector = new GestureDetector( getContext(), mGestureListener, null, true ); mCurrentScaleFactor = 1f; mDoubleTapDirection = 1; } @Override public void setImageRotateBitmapReset( RotateBitmap bitmap, boolean reset ) { super.setImageRotateBitmapReset( bitmap, reset ); 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; } protected float onDoubleTapPost( float scale, float maxZoom ) { if ( mDoubleTapDirection == 1 ) { if ( ( scale + ( mScaleFactor * 2 ) ) <= maxZoom ) { return scale + mScaleFactor; } else { mDoubleTapDirection = -1; return maxZoom; } } else { mDoubleTapDirection = 1; return 1f; } } class GestureListener extends GestureDetector.SimpleOnGestureListener { @Override public boolean onDoubleTap( MotionEvent e ) { 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(); return super.onDoubleTap( e ); } @Override public boolean onScroll( MotionEvent e1, MotionEvent e2, float distanceX, float distanceY ) { 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 ( 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 ); } } 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 ( true ) { 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; } } }