慕课网hyman大神的课
出处:https://www.imooc.com/video/6729
可自由拖动、放大缩小、双击的ImageView
public class ZoomImgView extends ImageView 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;//双击后 正在处理双击变化的过程 就不处理双击事件了
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;
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 && currentScale >mTargetScale)) {
postDelayed(this, 16);
}else {//设置为我们的目标值
float scale =mTargetScale / currentScale;
mScaleMatrix.postScale(scale, scale, x, y);
checkBorderAndCenterWhenScale();
setImageMatrix(mScaleMatrix);
isAutoScale =false;
}
}
}
public ZoomImgView(Context context) {
this(context, null);
}
public ZoomImgView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ZoomImgView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mScaleMatrix =new Matrix();
setScaleType(ScaleType.MATRIX);
mScaleGestureDetector =new ScaleGestureDetector(context, this);
setOnTouchListener(this);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
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() // mScaleMatrix.postScale(mMidScale / getScale(), mMidScale / getScale(), x, y); // checkBorderAndCenterWhenScale(); // setImageMatrix(mScaleMatrix); postDelayed(new AutoScaleRunnable(mMidScale, x, y), 16); isAutoScale =true; }else { // mScaleMatrix.postScale(mInitScale / getScale(), mInitScale / getScale(), x, y); // checkBorderAndCenterWhenScale(); // setImageMatrix(mScaleMatrix); postDelayed(new AutoScaleRunnable(mInitScale, x, y), 16); isAutoScale =true; } return true; } }); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); getViewTreeObserver().addOnGlobalLayoutListener(this); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); getViewTreeObserver().removeGlobalOnLayoutListener(this); } /** * 获取ImageView加载完成的图片 */ @Override public void onGlobalLayout() { if (!mOnce) { int width = getWidth(); int height = getHeight(); Drawable drawable = getDrawable(); if (drawable ==null) return; int drabWidth = drawable.getIntrinsicWidth(); int drabHeight = drawable.getIntrinsicHeight(); float scale =1.0f; //如果图片的宽度大于控件的宽度,但是图片的高度小于控件的高度,将其缩小 if (drabWidth > width && drabHeight < height) { scale = width *1.0f / drabWidth; } //如果图片的高度大于控件的高度,但是图片的宽度小于控件的宽度,将其缩小 if (drabHeight > height && drabWidth < width) { scale = height *1.0f / drabHeight; } //如果图片的宽高都大于控件的宽高或者宽高都小于控件的宽高,将其缩小/放大到合适的位置 if (drabWidth > width && drabHeight > height) { scale = Math.min(width *1.0f / drabWidth, height *1.0f / drabHeight); } if (drabWidth < width && drabHeight < height) { scale = Math.min(width *1.0f / drabWidth, height *1.0f / drabHeight); } //得到初始化时的缩放比例 mInitScale = scale; mMaxScale =mInitScale *4; mMidScale =mInitScale *2; //将图片移动至控件中心 int dx = getWidth() /2 - drabWidth /2; int dy = getHeight() /2 - drabHeight /2; mScaleMatrix.postTranslate(dx, dy); mScaleMatrix.postScale(mInitScale, mInitScale, width /2, height /2); setImageMatrix(mScaleMatrix); mOnce =true; } } //获取当前图片的缩放值 private float getScale() { float[] values =new float[9]; mScaleMatrix.getValues(values); return values[Matrix.MSCALE_X]; } @Override public boolean onScale(ScaleGestureDetector detector) { float scale = getScale(); float scaleFactor = detector.getScaleFactor(); if (getDrawable() ==null) return true; //缩小范围的控制 if ((scale if (scale * scaleFactor scaleFactor =mInitScale / scale; } if (scale * scaleFactor >mMaxScale) { scale =mMaxScale / scale; } //缩放 mScaleMatrix.postScale(scaleFactor, scaleFactor, detector.getFocusX(), detector.getFocusY()); checkBorderAndCenterWhenScale(); setImageMatrix(mScaleMatrix); } return true; } @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); } case MotionEvent.ACTION_MOVE: if (rectF.width() > getWidth() +0.01 || rectF.height() > getHeight() +0.01) { if (getParent()instanceof ViewPager) 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); checkBorderAndTranslate(); setImageMatrix(mScaleMatrix); } } mLastX = x; mLastY = y; break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: mLastPointerCount =0; break; } return true; } //当移动时进行边界检查 private void checkBorderAndTranslate() { RectF rectF = getMatrixRectF(); float deltaX =0; float deltaY =0; int width = getWidth(); int height = getHeight(); if (rectF.top >0 &&isCheckTopAndBottom) { deltaY = -rectF.top; } if (rectF.bottom < height &&isCheckTopAndBottom) { deltaY = height - rectF.bottom; } if (rectF.left >0 &&isCheckLeftAndRight) { deltaX = -rectF.left; } if (rectF.right < width &&isCheckLeftAndRight) { deltaX = width - rectF.right; } mScaleMatrix.postTranslate(deltaX, deltaY); } //判断是否足以触发move private boolean isMoveAction(float dx, float dy) { return Math.sqrt(dx * dx + dy * dy) >mTouchSlop; } //获得图片放大缩小以后的宽和高 以及margin private RectF getMatrixRectF() { Matrix matrix =mScaleMatrix; RectF rectF =new RectF(); Drawable drawable = getDrawable(); if (drawable !=null) { rectF.set(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); matrix.mapRect(rectF); } return rectF; } //再缩放时进行边界控制以及位置的控制 private void checkBorderAndCenterWhenScale() { RectF rect = getMatrixRectF(); float deltaX =0; float deltaY =0; int width = getWidth(); int height = getHeight(); //缩放时进行边界检测 if (rect.width() >= width) { if (rect.left >0) { deltaX = -rect.left; } if (rect.right < width) { deltaX = width - rect.right; } } if (rect.height() >= height) { if (rect.top >0) { deltaY = -rect.top; } if (rect.bottom < height) { deltaY = height - rect.bottom; } } //如果宽度或高度小于控件的宽或高 让其居中 if (rect.width() < width) { deltaX = width /2 - rect.right + rect.width() /2; } if (rect.height() < height) { deltaY = height /2 - rect.bottom + rect.height() /2; } mScaleMatrix.postTranslate(deltaX, deltaY); } } class ssactivity{ private ViewPagermViewPager; private int[]mImgs = {R.mipmap.guoma, R.mipmap.xue, R.mipmap.xuezhiqian}; private ImageView[]mImageViews =new ImageView[mImgs.length]; @Override protected void initView() { mViewPager = (ViewPager) findViewById(R.id.id_viewPager); mViewPager.setAdapter(new PagerAdapter() { @Override public ObjectinstantiateItem(ViewGroup container, int position) { ZoomImageView zoomImageView =new ZoomImageView(getApplicationContext()); zoomImageView.setImageResource(mImgs[position]); container.addView(zoomImageView); mImageViews[position] = zoomImageView; return zoomImageView; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView(mImageViews[position]); } @Override public int getCount() { return mImageViews.length; } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } }); } }activity代码