290 lines
8.6 KiB
Java
290 lines
8.6 KiB
Java
package com.gh.common.view;
|
|
|
|
import android.content.Context;
|
|
import android.graphics.*;
|
|
import android.net.Uri;
|
|
import android.util.AttributeSet;
|
|
import android.view.*;
|
|
import com.facebook.drawee.view.SimpleDraweeView;
|
|
import com.gh.gamecenter.eventbus.EBReuse;
|
|
import de.greenrobot.event.EventBus;
|
|
|
|
/**
|
|
* Created by khy on 2016/10/26.
|
|
*/
|
|
public class ZoomSimpleDraweeView extends SimpleDraweeView {
|
|
private final float[] matrixValues = new float[9];
|
|
private ScaleGestureDetector mScaleDetector;
|
|
private GestureDetector mGestureDetector;
|
|
private float mCurrentScale = 1f;
|
|
private Matrix mCurrentMatrix;
|
|
private setOnSingleClickListener mClickListener;
|
|
private setOnLongClickListener mLongClickListener;
|
|
private float imgagePro = -1; // 图片宽高比
|
|
|
|
public ZoomSimpleDraweeView(Context context) {
|
|
super(context);
|
|
init();
|
|
}
|
|
|
|
public ZoomSimpleDraweeView(Context context, AttributeSet attrs) {
|
|
super(context, attrs);
|
|
init();
|
|
}
|
|
|
|
public ZoomSimpleDraweeView(Context context, AttributeSet attrs, int defStyle) {
|
|
super(context, attrs, defStyle);
|
|
init();
|
|
}
|
|
|
|
private void init() {
|
|
mCurrentMatrix = new Matrix();
|
|
|
|
ScaleGestureDetector.OnScaleGestureListener scaleListener = new ScaleGestureDetector
|
|
.SimpleOnScaleGestureListener() {
|
|
|
|
@Override
|
|
public boolean onScale(ScaleGestureDetector detector) {
|
|
float scaleFactor = detector.getScaleFactor();
|
|
if (mCurrentScale < 4f || detector.getScaleFactor() < 1f) {
|
|
mCurrentScale *= scaleFactor;
|
|
mCurrentMatrix.postScale(scaleFactor, scaleFactor, detector.getFocusX(), detector.getFocusY());
|
|
invalidate();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public void onScaleEnd(ScaleGestureDetector detector) {
|
|
super.onScaleEnd(detector);
|
|
|
|
if (mCurrentScale < 1f) {
|
|
reset();
|
|
}
|
|
checkBorder();
|
|
}
|
|
|
|
};
|
|
mScaleDetector = new ScaleGestureDetector(getContext(), scaleListener);
|
|
|
|
GestureDetector.SimpleOnGestureListener gestureListener = new GestureDetector.SimpleOnGestureListener() {
|
|
@Override
|
|
public boolean onSingleTapConfirmed(MotionEvent e) {
|
|
if (mClickListener != null) {
|
|
mClickListener.onClick();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public void onLongPress(MotionEvent e) {
|
|
super.onLongPress(e);
|
|
if (mLongClickListener != null) {
|
|
mLongClickListener.onLongClick();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
|
|
if (mCurrentScale > 1f) {
|
|
mCurrentMatrix.postTranslate(-distanceX, -distanceY);
|
|
invalidate();
|
|
checkBorder();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean onDoubleTap(MotionEvent e) {
|
|
final float x = e.getX();
|
|
final float y = e.getY();
|
|
float scaleSize; //扩大或缩小的倍数
|
|
|
|
if (mCurrentScale > 1.5f) { //缩小时直接回到原画大小
|
|
scaleSize = 0.5f;
|
|
ZoomSimpleDraweeView.this.post(new AutoScaleRunnable(mCurrentScale * scaleSize, getWidth() / 2f, getHeight() / 2f, false));
|
|
} else {
|
|
scaleSize = 2.0f;
|
|
ZoomSimpleDraweeView.this.post(new AutoScaleRunnable(mCurrentScale * scaleSize, x, y, true));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean onSingleTapUp(MotionEvent e) {
|
|
|
|
return super.onSingleTapUp(e);
|
|
}
|
|
};
|
|
mGestureDetector = new GestureDetector(getContext(), gestureListener);
|
|
}
|
|
|
|
/**
|
|
* 检查图片边界是否移到view以内
|
|
* 目的是让图片边缘不要移动到view里面
|
|
*/
|
|
private void checkBorder() {
|
|
RectF rectF = getDisplayRect(mCurrentMatrix);
|
|
boolean reset = false;
|
|
float dx = 0;
|
|
float dy = 0;
|
|
|
|
|
|
if (rectF.left > 0) {
|
|
dx = getLeft() - rectF.left;
|
|
reset = true;
|
|
}
|
|
if (rectF.top > 0) {
|
|
dy = getTop() - rectF.top;
|
|
reset = true;
|
|
}
|
|
if (rectF.right < getRight()) {
|
|
dx = getRight() - rectF.right;
|
|
reset = true;
|
|
}
|
|
if (rectF.bottom < getHeight()) {
|
|
dy = getHeight() - rectF.bottom;
|
|
reset = true;
|
|
}
|
|
if (reset) {
|
|
mCurrentMatrix.postTranslate(dx, dy);
|
|
invalidate();
|
|
}
|
|
if (dy == 0 && reset || mCurrentScale == 1f) {
|
|
EventBus.getDefault().post(new EBReuse("isStopMove"));
|
|
} else {
|
|
EventBus.getDefault().post(new EBReuse("isStartove"));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper method that maps the supplied Matrix to the current Drawable
|
|
*
|
|
* @param matrix - Matrix to map Drawable against
|
|
* @return RectF - Displayed Rectangle
|
|
*/
|
|
private RectF getDisplayRect(Matrix matrix) {
|
|
// int bottom;
|
|
// if (imgagePro != -1){
|
|
// bottom = (int) (getRight()*imgagePro);
|
|
// } else {
|
|
// bottom = getBottom();
|
|
// }
|
|
RectF rectF = new RectF(getLeft(), getTop(), getRight(), getBottom());
|
|
matrix.mapRect(rectF);
|
|
return rectF;
|
|
}
|
|
|
|
@Override
|
|
public void setImageURI(Uri uri) {
|
|
reset();
|
|
super.setImageURI(uri);
|
|
}
|
|
|
|
@Override
|
|
protected void onDraw(Canvas canvas) {
|
|
int saveCount = canvas.save();
|
|
canvas.concat(mCurrentMatrix);
|
|
super.onDraw(canvas);
|
|
canvas.restoreToCount(saveCount);
|
|
}
|
|
|
|
@Override
|
|
public boolean onTouchEvent(MotionEvent event) {
|
|
mScaleDetector.onTouchEvent(event);
|
|
if (!mScaleDetector.isInProgress()) {
|
|
mGestureDetector.onTouchEvent(event);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* 重置图片
|
|
*/
|
|
public void reset() {
|
|
mCurrentMatrix.reset();
|
|
mCurrentScale = 1f;
|
|
invalidate();
|
|
EventBus.getDefault().post(new EBReuse("isStopMove"));
|
|
}
|
|
|
|
public final float getScale() {
|
|
mCurrentMatrix.getValues(matrixValues);
|
|
return matrixValues[Matrix.MSCALE_X];
|
|
}
|
|
|
|
//图片宽高比例
|
|
public void setImagePro(float imgPro) {
|
|
this.imgagePro = imgPro;
|
|
}
|
|
|
|
public void setOnSingleClickListener(setOnSingleClickListener listener) {
|
|
mClickListener = listener;
|
|
}
|
|
|
|
public void setOnLongClickListener(setOnLongClickListener listener) {
|
|
mLongClickListener = listener;
|
|
}
|
|
|
|
public interface setOnLongClickListener {
|
|
void onLongClick();
|
|
}
|
|
|
|
public interface setOnSingleClickListener {
|
|
void onClick();
|
|
}
|
|
|
|
/**
|
|
* 自动缩放的任务
|
|
*/
|
|
private class AutoScaleRunnable implements Runnable {
|
|
static final float BIGGER = 1.07f;
|
|
static final float SMALLER = 0.96f;
|
|
private float mTargetScale;
|
|
private boolean isExp;
|
|
|
|
/**
|
|
* 缩放的中心
|
|
*/
|
|
private float x;
|
|
private float y;
|
|
|
|
/**
|
|
* @param isExp :判断是否是放大
|
|
*/
|
|
public AutoScaleRunnable(float targetScale, float x, float y, boolean isExp) {
|
|
this.mTargetScale = targetScale;
|
|
this.x = x;
|
|
this.y = y;
|
|
this.isExp = isExp;
|
|
|
|
}
|
|
|
|
@Override
|
|
public void run() {
|
|
if (isExp) { //放大
|
|
mCurrentMatrix.postScale(BIGGER, BIGGER, x, y);
|
|
invalidate();
|
|
if (mCurrentScale < mTargetScale && mCurrentScale <= 4) {
|
|
ZoomSimpleDraweeView.this.postDelayed(this, 10);
|
|
mCurrentScale = mCurrentScale * BIGGER;
|
|
} else {
|
|
checkBorder();
|
|
mCurrentScale = getScale();
|
|
}
|
|
} else {//缩小
|
|
mCurrentMatrix.postScale(SMALLER, SMALLER, x, y);
|
|
invalidate();
|
|
checkBorder();
|
|
if (getScale() > 1.01) {
|
|
ZoomSimpleDraweeView.this.postDelayed(this, 1);
|
|
mCurrentScale = mCurrentScale * SMALLER;
|
|
} else {
|
|
reset();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|