Created
May 31, 2018 10:08
-
-
Save ganeshr-iprogrammer/31d0b82f00f1f21cadb838a7b99149b1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.content.Context; | |
import android.graphics.Matrix; | |
import android.graphics.PointF; | |
import android.graphics.drawable.Drawable; | |
import android.util.AttributeSet; | |
import android.util.Log; | |
import android.view.MotionEvent; | |
import android.view.ScaleGestureDetector; | |
import android.view.View; | |
import android.widget.ImageView; | |
public class TouchImageView extends ImageView { | |
Matrix matrix; | |
// We can be in one of these 3 states | |
static final int NONE = 0; | |
static final int DRAG = 1; | |
static final int ZOOM = 2; | |
int mode = NONE; | |
// Remember some things for zooming | |
PointF last = new PointF(); | |
PointF start = new PointF(); | |
float minScale = 1f; | |
float maxScale = 3f; | |
float[] m; | |
int viewWidth, viewHeight; | |
static final int CLICK = 3; | |
float saveScale = 1f; | |
protected float origWidth, origHeight; | |
int oldMeasuredWidth, oldMeasuredHeight; | |
ScaleGestureDetector mScaleDetector; | |
Context context; | |
public TouchImageView(Context context) { | |
super(context); | |
sharedConstructing(context); | |
} | |
public TouchImageView(Context context, AttributeSet attrs) { | |
super(context, attrs); | |
sharedConstructing(context); | |
} | |
private void sharedConstructing(Context context) { | |
super.setClickable(true); | |
this.context = context; | |
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); | |
matrix = new Matrix(); | |
m = new float[9]; | |
setImageMatrix(matrix); | |
setScaleType(ScaleType.MATRIX); | |
setOnTouchListener(new OnTouchListener() { | |
@Override | |
public boolean onTouch(View v, MotionEvent event) { | |
mScaleDetector.onTouchEvent(event); | |
PointF curr = new PointF(event.getX(), event.getY()); | |
switch (event.getAction()) { | |
case MotionEvent.ACTION_DOWN: | |
last.set(curr); | |
start.set(last); | |
mode = DRAG; | |
break; | |
case MotionEvent.ACTION_MOVE: | |
if (mode == DRAG) { | |
float deltaX = curr.x - last.x; | |
float deltaY = curr.y - last.y; | |
float fixTransX = getFixDragTrans(deltaX, viewWidth, | |
origWidth * saveScale); | |
float fixTransY = getFixDragTrans(deltaY, viewHeight, | |
origHeight * saveScale); | |
matrix.postTranslate(fixTransX, fixTransY); | |
fixTrans(); | |
last.set(curr.x, curr.y); | |
} | |
break; | |
case MotionEvent.ACTION_UP: | |
mode = NONE; | |
int xDiff = (int) Math.abs(curr.x - start.x); | |
int yDiff = (int) Math.abs(curr.y - start.y); | |
if (xDiff < CLICK && yDiff < CLICK) | |
performClick(); | |
break; | |
case MotionEvent.ACTION_POINTER_UP: | |
mode = NONE; | |
break; | |
} | |
setImageMatrix(matrix); | |
invalidate(); | |
return true; // indicate event was handled | |
} | |
}); | |
} | |
public void setMaxZoom(float x) { | |
maxScale = x; | |
} | |
private class ScaleListener extends | |
ScaleGestureDetector.SimpleOnScaleGestureListener { | |
@Override | |
public boolean onScaleBegin(ScaleGestureDetector detector) { | |
mode = ZOOM; | |
return true; | |
} | |
@Override | |
public boolean onScale(ScaleGestureDetector detector) { | |
float mScaleFactor = detector.getScaleFactor(); | |
float origScale = saveScale; | |
saveScale *= mScaleFactor; | |
if (saveScale > maxScale) { | |
saveScale = maxScale; | |
mScaleFactor = maxScale / origScale; | |
} else if (saveScale < minScale) { | |
saveScale = minScale; | |
mScaleFactor = minScale / origScale; | |
} | |
if (origWidth * saveScale <= viewWidth | |
|| origHeight * saveScale <= viewHeight) | |
matrix.postScale(mScaleFactor, mScaleFactor, viewWidth / 2, | |
viewHeight / 2); | |
else | |
matrix.postScale(mScaleFactor, mScaleFactor, | |
detector.getFocusX(), detector.getFocusY()); | |
fixTrans(); | |
return true; | |
} | |
} | |
void fixTrans() { | |
matrix.getValues(m); | |
float transX = m[Matrix.MTRANS_X]; | |
float transY = m[Matrix.MTRANS_Y]; | |
float fixTransX = getFixTrans(transX, viewWidth, origWidth * saveScale); | |
float fixTransY = getFixTrans(transY, viewHeight, origHeight | |
* saveScale); | |
if (fixTransX != 0 || fixTransY != 0) | |
matrix.postTranslate(fixTransX, fixTransY); | |
} | |
float getFixTrans(float trans, float viewSize, float contentSize) { | |
float minTrans, maxTrans; | |
if (contentSize <= viewSize) { | |
minTrans = 0; | |
maxTrans = viewSize - contentSize; | |
} else { | |
minTrans = viewSize - contentSize; | |
maxTrans = 0; | |
} | |
if (trans < minTrans) | |
return -trans + minTrans; | |
if (trans > maxTrans) | |
return -trans + maxTrans; | |
return 0; | |
} | |
float getFixDragTrans(float delta, float viewSize, float contentSize) { | |
if (contentSize <= viewSize) { | |
return 0; | |
} | |
return delta; | |
} | |
@Override | |
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { | |
super.onMeasure(widthMeasureSpec, heightMeasureSpec); | |
viewWidth = MeasureSpec.getSize(widthMeasureSpec); | |
viewHeight = MeasureSpec.getSize(heightMeasureSpec); | |
// | |
// Rescales image on rotation | |
// | |
if (oldMeasuredHeight == viewWidth && oldMeasuredHeight == viewHeight | |
|| viewWidth == 0 || viewHeight == 0) | |
return; | |
oldMeasuredHeight = viewHeight; | |
oldMeasuredWidth = viewWidth; | |
if (saveScale == 1) { | |
// Fit to screen. | |
float scale; | |
Drawable drawable = getDrawable(); | |
if (drawable == null || drawable.getIntrinsicWidth() == 0 | |
|| drawable.getIntrinsicHeight() == 0) | |
return; | |
int bmWidth = drawable.getIntrinsicWidth(); | |
int bmHeight = drawable.getIntrinsicHeight(); | |
Log.d("bmSize", "bmWidth: " + bmWidth + " bmHeight : " + bmHeight); | |
float scaleX = (float) viewWidth / (float) bmWidth; | |
float scaleY = (float) viewHeight / (float) bmHeight; | |
scale = Math.min(scaleX, scaleY); | |
matrix.setScale(scale, scale); | |
// Center the image | |
float redundantYSpace = (float) viewHeight | |
- (scale * (float) bmHeight); | |
float redundantXSpace = (float) viewWidth | |
- (scale * (float) bmWidth); | |
redundantYSpace /= (float) 2; | |
redundantXSpace /= (float) 2; | |
matrix.postTranslate(redundantXSpace, redundantYSpace); | |
origWidth = viewWidth - 2 * redundantXSpace; | |
origHeight = viewHeight - 2 * redundantYSpace; | |
setImageMatrix(matrix); | |
} | |
fixTrans(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment