ZoomableImageView in Android
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.widget.ImageView;
public class ZoomableImageView extends ImageView {
private ScaleGestureDetector scaleGestureDetector;
private Matrix matrix = new Matrix();
private PointF lastTouchPoint = new PointF();
private float[] matrixValues = new float[9];
public ZoomableImageView(Context context) {
super(context);
setup(context);
}
public ZoomableImageView(Context context, AttributeSet attrs) {
super(context, attrs);
setup(context);
}
public ZoomableImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setup(context);
}
private void setup(Context context) {
setScaleType(ScaleType.MATRIX);
scaleGestureDetector = new ScaleGestureDetector(context, new ScaleGestureDetector.SimpleOnScaleGestureListener() {
@Override
public boolean onScale(ScaleGestureDetector detector) {
float scaleFactor = detector.getScaleFactor();
matrix.postScale(scaleFactor, scaleFactor, detector.getFocusX(), detector.getFocusY());
setImageMatrix(matrix);
return true;
}
});
}
@Override
public boolean onTouchEvent(MotionEvent event) {
scaleGestureDetector.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
lastTouchPoint.set(event.getX(), event.getY());
break;
case MotionEvent.ACTION_MOVE:
float deltaX = event.getX() - lastTouchPoint.x;
float deltaY = event.getY() - lastTouchPoint.y;
matrix.getValues(matrixValues);
float scale = matrixValues[Matrix.MSCALE_X];
float translateX = matrixValues[Matrix.MTRANS_X];
float translateY = matrixValues[Matrix.MTRANS_Y];
float imageWidth = getDrawable().getIntrinsicWidth() * scale;
float imageHeight = getDrawable().getIntrinsicHeight() * scale;
if (imageWidth < getWidth()) {
deltaX = 0;
translateX = getWidth() / 2 - imageWidth / 2;
} else if (translateX + deltaX > 0) {
deltaX = -translateX;
} else if (translateX + deltaX < getWidth() - imageWidth) {
deltaX = getWidth() - imageWidth - translateX;
}
if (imageHeight < getHeight()) {
deltaY = 0;
translateY = getHeight() / 2 - imageHeight / 2;
} else if (translateY + deltaY > 0) {
deltaY = -translateY;
} else if (translateY + deltaY < getHeight() - imageHeight) {
deltaY = getHeight() - imageHeight - translateY;
}
matrix.postTranslate(deltaX, deltaY);
lastTouchPoint.set(event.getX(), event.getY());
setImageMatrix(matrix);
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
public void rotate(float degrees) {
matrix.postRotate(degrees, getWidth() / 2f, getHeight() / 2f);
setImageMatrix(matrix);
}
}