package com.example.administrator.jingdong.view; import android.content.Context; import android.graphics.Matrix; import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.util.Log; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.ScaleGestureDetector; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewTreeObserver; /** * Created by admin on 2018/1/19. */ public class ZoomImageView extends android.support.v7.widget.AppCompatImageView implements ViewTreeObserver.OnGlobalLayoutListener, ScaleGestureDetector.OnScaleGestureListener, View.OnTouchListener { private boolean mOnce; /** * 初始化时缩放的值 */ private float mInitScale; /** * 双击放大值到达的值 */ private float mMidScale; /** * 放大的最大值 */ private float mMaxScale; private Matrix mScaleMatrix; /** * 捕获用户多指触控时缩放的比例 */ private ScaleGestureDetector mScaleGestureDetector; // **********自由移动的变量*********** /** * 记录上一次多点触控的数量 */ private int mLastPointerCount; private float mLastX; private float mLastY; private int mTouchSlop; private boolean isCanDrag; private boolean isCheckLeftAndRight; private boolean isCheckTopAndBottom; // *********双击放大与缩小********* private GestureDetector mGestureDetector; private boolean isAutoScale; public ZoomImageView(Context context) { this(context, null); } public ZoomImageView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ZoomImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // init mScaleMatrix = new Matrix(); setScaleType(ScaleType.MATRIX); setOnTouchListener(this); mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); mScaleGestureDetector = new ScaleGestureDetector(context, this); mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { @Override public boolean onDoubleTap(MotionEvent e) { if (isAutoScale) { return true; } float x = e.getX(); float y = e.getY(); if (getScale() < mMidScale) { postDelayed(new AutoScaleRunnable(mMidScale, x, y), 16); isAutoScale = true; } else { postDelayed(new AutoScaleRunnable(mInitScale, x, y), 16); isAutoScale = true; } return true; } }); } /** * 自动放大与缩小 * * @author zhangyan@lzt.com.cn * */ private class AutoScaleRunnable implements Runnable { /** * 缩放的目标值 */ private float mTargetScale; // 缩放的中心点 private float x; private float y; private final float BIGGER = 1.07f; private final float SMALL = 0.93f; private float tmpScale; /** * @param mTargetScale * @param x * @param y */ public AutoScaleRunnable(float mTargetScale, float x, float y) { this.mTargetScale = mTargetScale; this.x = x; this.y = y; if (getScale() < mTargetScale) { tmpScale = BIGGER; } if (getScale() > mTargetScale) { tmpScale = SMALL; } } @Override public void run() { //进行缩放 mScaleMatrix.postScale(tmpScale, tmpScale, x, y); checkBorderAndCenterWhenScale(); setImageMatrix(mScaleMatrix); float currentScale = getScale(); if ((tmpScale >1.0f && currentScale <mTargetScale) ||(tmpScale<1.0f &¤tScale>mTargetScale)) { //这个方法是重新调用run()方法 postDelayed(this, 16); }else{ //设置为我们的目标值 float scale = mTargetScale/currentScale; mScaleMatrix.postScale(scale, scale, x, y); checkBorderAndCenterWhenScale(); setImageMatrix(mScaleMatrix); isAutoScale = false; } } } /** * 获取ImageView加载完成的图片 */ @Override public void onGlobalLayout() { if (!mOnce) { // 得到控件的宽和高 int width = getWidth(); int height = getHeight(); // 得到我们的图片,以及宽和高 Drawable drawable = getDrawable(); if (drawable == null) { return; } int dh = drawable.getIntrinsicHeight(); int dw = drawable.getIntrinsicWidth(); float scale = 0.5f; // 图片的宽度大于控件的宽度,图片的高度小于空间的高度,我们将其缩小 if (dw > width && dh < height) { scale = width * 1.0f / dw; } // 图片的宽度小于控件的宽度,图片的高度大于空间的高度,我们将其缩小 if (dh > height && dw < width) { scale = height * 1.0f / dh; } // 缩小值 if (dw > width && dh > height) { scale = Math.min(width * 1.0f / dw, height * 1.0f / dh); } // 放大值 if (dw < width && dh < height) { scale = Math.min(width * 1.0f / dw, height * 1.0f / dh); } /** * 得到了初始化时缩放的比例 */ mInitScale = scale; mMaxScale = mInitScale * 4; mMidScale = mInitScale * 2; // 将图片移动至控件的中间 int dx = getWidth() / 2 - dw / 2; int dy = getHeight() / 2 - dh / 2; mScaleMatrix.postTranslate(dx, dy); mScaleMatrix.postScale(mInitScale, mInitScale, width / 2, height / 2); setImageMatrix(mScaleMatrix); mOnce = true; } } /** * 注册OnGlobalLayoutListener这个接口 */ @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); getViewTreeObserver().addOnGlobalLayoutListener(this); } /** * 取消OnGlobalLayoutListener这个接口 */ @SuppressWarnings("deprecation") @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); getViewTreeObserver().removeGlobalOnLayoutListener(this); } /** * 获取当前图片的缩放值 * * @return */ public float getScale() { float[] values = new float[9]; mScaleMatrix.getValues(values); return values[Matrix.MSCALE_X]; } // 缩放区间时initScale maxScale @Override public boolean onScale(ScaleGestureDetector detector) { float scale = getScale(); float scaleFactor = detector.getScaleFactor(); if (getDrawable() == null) { return true; } // 缩放范围的控制 if ((scale < mMaxScale && scaleFactor > 1.0f) || (scale > mInitScale && scaleFactor < 1.0f)) { if (scale * scaleFactor < mInitScale) { scaleFactor = mInitScale / scale; } if (scale * scaleFactor > mMaxScale) { scale = mMaxScale / scale; } // 缩放 mScaleMatrix.postScale(scaleFactor, scaleFactor, detector.getFocusX(), detector.getFocusY()); checkBorderAndCenterWhenScale(); setImageMatrix(mScaleMatrix); } return true; } /** * 获得图片放大缩小以后的宽和高,以及left,right,top,bottom * * @return */ private RectF getMatrixRectF() { Matrix matrix = mScaleMatrix; RectF rectF = new RectF(); Drawable d = getDrawable(); if (d != null) { rectF.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight()); matrix.mapRect(rectF); } return rectF; } /** * 在缩放的时候进行边界以及我们的位置的控制 */ private void checkBorderAndCenterWhenScale() { RectF rectF = getMatrixRectF(); float deltaX = 0; float deltaY = 0; int width = getWidth(); int height = getHeight(); // 缩放时进行边界检测,防止出现白边 if (rectF.width() >= width) { if (rectF.left > 0) { deltaX = -rectF.left; } if (rectF.right < width) { deltaX = width - rectF.right; } } if (rectF.height() >= height) { if (rectF.top > 0) { deltaY = -rectF.top; } if (rectF.bottom < height) { deltaY = height - rectF.bottom; } } /** * 如果宽度或高度小于空间的宽或者高,则让其居中 */ if (rectF.width() < width) { deltaX = width / 2f - rectF.right + rectF.width() / 2f; } if (rectF.height() < height) { deltaY = height / 2f - rectF.bottom + rectF.height() / 2f; } mScaleMatrix.postTranslate(deltaX, deltaY); } @Override public boolean onScaleBegin(ScaleGestureDetector detector) { return true; } @Override public void onScaleEnd(ScaleGestureDetector detector) { } @Override public boolean onTouch(View v, MotionEvent event) { if (mGestureDetector.onTouchEvent(event)) { return true; } mScaleGestureDetector.onTouchEvent(event); float x = 0; float y = 0; // 拿到多点触控的数量 int pointerCount = event.getPointerCount(); for (int i = 0; i < pointerCount; i++) { x += event.getX(i); y += event.getY(i); } x /= pointerCount; y /= pointerCount; if (mLastPointerCount != pointerCount) { isCanDrag = false; mLastX = x; mLastY = y; } mLastPointerCount = pointerCount; RectF rectF = getMatrixRectF(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: if (rectF.width()>getWidth() +0.01|| rectF.height()>getHeight()+0.01) { if(getParent() instanceof ViewPager) getParent().requestDisallowInterceptTouchEvent(true); } break; case MotionEvent.ACTION_MOVE: if (rectF.width()>getWidth()+0.01 || rectF.height()>getHeight()+0.01) { if(getParent() instanceof ViewPager){ Log.e("---","----+++"); getParent().requestDisallowInterceptTouchEvent(true); } } float dx = x - mLastX; float dy = y - mLastY; if (!isCanDrag) { isCanDrag = isMoveAction(dx, dy); } if (isCanDrag) { if (getDrawable() != null) { isCheckLeftAndRight = isCheckTopAndBottom = true; // 如果宽度小于控件宽度,不允许横向移动 if (rectF.width() < getWidth()) { isCheckLeftAndRight = false; dx = 0; } // 如果高度小于控件高度,不允许纵向移动 if (rectF.height() < getHeight()) { isCheckTopAndBottom = false; dy = 0; } mScaleMatrix.postTranslate(dx, dy); checkBorderWhenTranslate(); setImageMatrix(mScaleMatrix); } } mLastX = x; mLastY = y; break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: mLastPointerCount = 0; break; default: break; } return true; } /** * 当移动时进行边界检查 */ private void checkBorderWhenTranslate() { RectF rectF = getMatrixRectF(); float deltaX = 0; float deltaY = 0; int width = getWidth(); int heigth = getHeight(); if (rectF.top > 0 && isCheckTopAndBottom) { deltaY = -rectF.top; } if (rectF.bottom < heigth && isCheckTopAndBottom) { deltaY = heigth - rectF.bottom; } if (rectF.left > 0 && isCheckLeftAndRight) { deltaX = -rectF.left; } if (rectF.right < width && isCheckLeftAndRight) { deltaX = width - rectF.right; } mScaleMatrix.postTranslate(deltaX, deltaY); } /** * 判断是否是move * * @param dx * @param dy * @return */ private boolean isMoveAction(float dx, float dy) { return Math.sqrt(dx * dx + dy * dy) > mTouchSlop; } }//自己重写的俩个方法(必须手动写,不要忘记) @Override public Object instantiateItem(ViewGroup container, int position) { ZoomImageView zoomImageView=new ZoomImageView(FLXiangQingActivityZi.this); Glide.with(FLXiangQingActivityZi.this).load(list.get(position)).into(zoomImageView); container.addView(zoomImageView); return zoomImageView; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); }
双击图片放大缩小
最新推荐文章于 2021-12-25 22:46:17 发布