ZoomImageView是一个类似photoview的图片预览控件,实现了对图片的手势放大缩小平移,以及双击放大缩小解决和viewpager滑动冲突等功能,主要是通过GestureDetector,Matrix相关api以及对事件的ontouch处理实现的,这个代码网上能搜索到很多,但是因为注释少所以要完全读懂有些困难,于是本人整理了一段时间,写了一个完整的注释版本,基本每行代码都做到了讲解,大家共同学习。
public class ZoomImageView extends ImageView implements ViewTreeObserver.OnGlobalLayoutListener,ScaleGestureDetector.OnScaleGestureListener,View.OnTouchListener{
@SuppressWarnings("unused")
private static final String TAG = "ZoomImageView";
/**
* 最大放大倍数
*/
public static final float mMaxScale = 4.0f;
/**
* 默认缩放
*/
private float mInitScale = 1.0f;
/**
* 双击放大比例
*/
private float mMidScale=2.0f;
/**
* 检测缩放手势 多点触控手势识别 独立的类不是GestureDetector的子类
*/
ScaleGestureDetector mScaleGestureDetector = null;//检测缩放的手势
/**
*检测类似长按啊 轻按啊 拖动 快速滑动 双击啊等等 OnTouch方法虽然也可以
* 但是对于一些复杂的手势需求自己去通过轨迹时间等等判断很复杂,因此我们采用系统
* 提供的手势类进行处理
*/
private GestureDetector mGestureDetector;
/**
* 如果正在缩放中就不向下执行,防止多次双击
*/
private boolean mIsAutoScaling;
/**
* Matrix的对图像的处理
* Translate 平移变换
* Rotate 旋转变换
* Scale 缩放变换
* Skew 错切变换
*/
Matrix mScaleMatrix = new Matrix();
/**
* 处理矩阵的9个值
*/
float[] mMartixValue = new float[9];
public ZoomImageView(Context context) {
this(context, null);
}
public ZoomImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ZoomImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setScaleType(ScaleType.MATRIX);
mScaleGestureDetector = new ScaleGestureDetector(context, this);
this.setOnTouchListener(this); //缩放的捕获要建立在setOnTouchListener上
//符合滑动的距离 它获得的是触发移动事件的最短距离,如果小于这个距离就不触发移动控件,
//如viewpager就是用这个距离来判断用户是否翻页
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
//监听双击事件 SimpleOnGestureListener是OnGestureListener接口实现类,
//使用这个复写需要的方法就可以不用复写所有的方法
mGestureDetector = new GestureDetector(context,
new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onDoubleTap(MotionEvent e) {
//如果正在缩放中就不向下执行,防止多次双击
if (mIsAutoScaling) {
return true;
}
//缩放的中心点
float x = e.getX();
float y = e.getY();
//如果当前缩放值小于这个临界值 则进行放大
if (getScale() < mMidScale) {
mIsAutoScaling = true;
//view中的方法 已x,y为坐标点放大到mMidScale 延时10ms
postDelayed(new AutoScaleRunble(mMidScale, x, y), 16);
} else {
//如果当前缩放值大于这个临界值 则进行缩小操作 缩小到mInitScale
mIsAutoScaling = true;
postDelayed(new AutoScaleRunble(mInitScale, x, y), 16);
}
return true;
}
});
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
getViewTreeObserver().addOnGlobalLayoutListener(this);
}
//suppress deprecate warning because i have dealt with it