ImageView gesture / Double-click to zoom

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.View;
import android.widget.ImageView;

/**
* ImageView手势/双击可缩放
* Created on 2019/11/4.
*/
public class GestureImageView extends ImageView implements View.OnTouchListener {

public class ZoomMode{
public final static int Ordinary = 0;
public final static int ZoomIn = 1;
public final static int DoubleZoomIn = 2;
}

private int curMode=0;
private Matrix matrix;
private PointF viewSize;
private PointF imageSize;
private PointF scaleSize;

//记录图片当前坐标
private PointF curPoint;
private PointF originScale;

//0:宽度适应 1:高度适应
private int fitMode=0;
private PointF start;
private PointF center;
private float scaleDoubleZoom=0;
private PointF relativePoint;
private float doubleFingerDistance=0;

long doubleClickTimeSpan=280;
long lastClickTime=0;
int rationZoomIn=2;

public void GestureImageViewInit(){
this.setOnTouchListener(this);
this.setScaleType(ScaleType.MATRIX);
matrix = new Matrix();
originScale = new PointF();
scaleSize = new PointF();
start = new PointF();
center = new PointF();
curPoint = new PointF();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
viewSize = new PointF(width, height);

//获取当前Drawable的大小
Drawable drawable = getDrawable();
IF (the drawable == null) {
Log.e ( "NO the drawable", "IS nullptr the drawable");
imageSize of PointF new new = (width, height / 2);
} the else {
imageSize of PointF new new = (drawable.getMinimumWidth (), drawable.getMinimumHeight ());
}

FitCenter ();
}

/ **
* that the image stored in a central
* /
public void FitCenter () {
a float scaleH = viewSize.y / imageSize.y;
a float scaleW = viewSize.x / imageSize. the X-;
// choose a small scaling factor to ensure the picture shows all within view of
float scale = scaleH <scaleW scaleH:? scaleW;
// adapt according to the size of the View
setImageScale (new new array of PointF (scale, scale));

originScale.set (scale, scale);
// resize the image to the center-to-center view size according to the scaling factor
IF (scaleH <scaleW) {
setImageTranslation (new new of PointF (viewSize.x / 2 - scaleSize.x / 2, 0));
fitMode =. 1;
} the else {
fitMode 0 =;
setImageTranslation (new new of PointF (0, viewSize.y / 2 - scaleSize.y / 2));
}

// continue recording the next scale factor from the zoom ratio
scaleDoubleZoom = originScale.x;
}


public GestureImageView (the context context) {
Super (context);
GestureImageViewInit ();
}

public GestureImageView (the context context, AttributeSet attrs) {
Super (context, attrs);
GestureImageViewInit ();
}

public GestureImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
GestureImageViewInit();
}


@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
start.set(event.getX(), event.getY());
//手指按下事件
if (event.getPointerCount() == 1) {
if (event.getEventTime()-lastClickTime <= doubleClickTimeSpan) {
//双击事件触发
Log.e("TouchEvent", "DoubleClick");
if (curMode == ZoomMode.Ordinary) {
curMode = ZoomMode.ZoomIn;
relativePoint = new PointF();
//计算归一化坐标
relativePoint.set( (start.x-curPoint.x)/scaleSize.x, (start.y-curPoint.y)/scaleSize.y );

setImageScale(new PointF(originScale.x * rationZoomIn, originScale.y * rationZoomIn));
setImageTranslation(new PointF(start.x - relativePoint.x * scaleSize.x, start.y - relativePoint.y * scaleSize.y));
} else {
curMode = ZoomMode.Ordinary;
FitCenter();
}
} The else {
lastClickTime event.getEventTime = ();
}
}
BREAK;
Case MotionEvent.ACTION_POINTER_DOWN:
// already hold the point on the screen and press a point when the trigger event
doubleFingerDistance = getDoubleFingerDistance (Event);
BREAK;
Case the MotionEvent .ACTION_POINTER_UP:
// already has two points on the screen press and release it when the event is triggered
curMode = ZoomMode.ZoomIn;
scaleDoubleZoom = scaleSize.x / imageSize.x;
IF (scaleSize.x <viewSize.x && scaleSize. y <viewSize.y) {
= ZoomMode.Ordinary curMode;
FitCenter ();
}
BREAK;
Case MotionEvent.ACTION_MOVE:
// event is triggered when the finger is moved
IF (event.getPointerCount () ==. 1) {
IF (curMode == ZoomMode.ZoomIn) {
setImageTranslation (new new of PointF (event.getX () - start.x, event.getY () - start.y));
start.set (event.getX (), event.getY ());
}
} the else {
// pinch zoom when judged whether a certain distance
if (Math.abs (getDoubleFingerDistance (event) -! doubleFingerDistance)> 50 && curMode = ZoomMode.DoubleZoomIn) {
// Get the midpoint of two fingers
center.set ((event.getX (0) + event.getX (. 1)) / 2, (event.getY (0) + event.getY (. 1)) / 2);
// set the start
start.set (Center);
curMode = ZoomMode.DoubleZoomIn;
doubleFingerDistance = getDoubleFingerDistance (Event);
relativePoint of PointF new new = ();

// current image according to the coordinate value calculating normalized coordinate
relativePoint.set ((start.x- curPoint.x) / scaleSize.x, (start.y-curPoint.y) /scaleSize.y);
}

IF (curMode == ZoomMode.DoubleZoomIn) {
* Scale = scaleDoubleZoom getDoubleFingerDistance a float (Event) / doubleFingerDistance;
setImageScale (new new of PointF (Scale, Scale));
setImageTranslation (new new of PointF (start.x - relativePoint.x * scaleSize.x, start.y - relativePoint.y * scaleSize. the y-));
}
}
BREAK;
Case MotionEvent.ACTION_UP:
// trigger finger release event

BREAK;
}

// note that it must be true here otherwise it will return the trigger down event
return true;
}


/ **
* according to zoom factor to scale the image
* @param scale
* /
public void setImageScale (array of PointF scale) {
matrix.setScale(scale.x, scale.y);
scaleSize.set(scale.x*imageSize.x, scale.y*imageSize.y);
this.setImageMatrix(matrix);
}

/**
* 根据偏移量改变图片位置
* @param offset
*/
public void setImageTranslation (PointF offset) {
matrix.postTranslate(offset.x, offset.y);
curPoint.set(offset);
this.setImageMatrix(matrix);
}

public static float getDoubleFingerDistance (MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return (float)Math.sqrt(x * x + y * y);
}

}

Guess you like

Origin www.cnblogs.com/achen0502/p/11796362.html