package com.gh.common.view; import android.content.Context; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.RectF; import android.net.Uri; import android.util.AttributeSet; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.ScaleGestureDetector; import com.facebook.drawee.view.SimpleDraweeView; import com.gh.gamecenter.eventbus.EBReuse; import org.greenrobot.eventbus.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(); } 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 onSingleTapUp(MotionEvent e) { return super.onSingleTapUp(e); } @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 onSingleTapConfirmed(MotionEvent e) { if (mClickListener != null) { mClickListener.onClick(); } return true; } }; mGestureDetector = new GestureDetector(getContext(), gestureListener); } /** * 重置图片 */ public void reset() { mCurrentMatrix.reset(); mCurrentScale = 1f; invalidate(); EventBus.getDefault().post(new EBReuse("isStopMove")); } /** * 检查图片边界是否移到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; } public ZoomSimpleDraweeView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public ZoomSimpleDraweeView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } @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 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(); } } } } }