慕课网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()<mMidScale) {
// 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 <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;
}
@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);
}
}
activity代码
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;
}
});
}
}
网友评论