从现在开始做学习博客,记录自己的Android学习历程。
最近一直做Android图片方面的研究,今天遇到了图片的拖拽和缩放问题,百度n多资料,自己边想边摸索,终于解决。现将源码贴下,我在真机上测试很流畅。
主要类:
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.util.FloatMath;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.ImageView;
public class FlexibleImageView extends ImageView {
private int mode;
private final int drag = 0;
private final int zoom = 1;
private final int none = 3;
private float startDis;
private Matrix matrix;
private PointF startF;
private PointF midPoint;
public FlexibleImageView(Context context) {
super(context);
init();
}
public FlexibleImageView(Context context, AttributeSet attrs) {
super(context, attrs, 0);
init();
}
private void init(){
matrix = this.getImageMatrix();
startF = new PointF();
//这个一定要设置
setScaleType(ScaleType.MATRIX);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
mode = drag;
startF.set(event.getX(), event.getY());
break;
case MotionEvent.ACTION_UP:
mode = none;
break;
case MotionEvent.ACTION_POINTER_DOWN:
mode = zoom;
startDis = getDis(event);
break;
case MotionEvent.ACTION_POINTER_UP:
mode = none;
break;
case MotionEvent.ACTION_MOVE:
// 这里做动作的处理
switch (mode) {
case drag:
// 移动
float x = event.getX() - startF.x;
float y = event.getY() - startF.y;
if (Math.abs(x) > 10 || Math.abs(y) > 10) {
matrix.postTranslate(x, y);
}
//关键代码
startF.set(event.getX(), event.getY());
break;
case zoom:
// 放大
float endDis = getDis(event);
float scale = endDis / startDis;
midPoint = getMidPoint(event);
//将缩放的比例控制在2.0到0.5之间
scale = scale > 1.8f ? 1.8f : scale;
scale = scale < 0.7f ? 0.7f : scale;
//怎么控制缩放的过程能够平缓
matrix.postScale(scale, scale, midPoint.x,
midPoint.y);
//关键代码
startDis = endDis;
break;
}
this.setImageMatrix(matrix);
break;
}
return true;
}
/**
* 获取放大的参照中点
*
* @param event
* @return
*/
private PointF getMidPoint(MotionEvent event) {
PointF point = new PointF();
float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
point.set(x / 2, y / 2);
return point;
}
/**
* 计算两点之间的距离
*
* @param event
* @return
*/
private float getDis(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return FloatMath.sqrt(x * x + y * y);
}
}
为了以后方便使用,我继承了ImageView类,对触摸事件实现监听,要点是对用户触摸事件的处理逻辑,其中有两行关键的代码,在Android的触摸事件中,用户手指在屏幕上的移动事件--ACTION_MOVE事件不是一次完成的,而是多个ACTION_MOVE事件对应用户的一次移动事件,所以如果那两行关键的代码不写会导致图片的拖拽和缩放和非常突兀,不跟手,这也卡了我一个晚上。还有,我这里对用户的缩放添加了控制,但是没有达到实际的效果,Matix缩放的原理我不是很清楚,如果图片放得足够大不知道会不会OOM,我在测试的时候没有出现,这个还有待测试。
顺便将我测试的Demo贴上,这里面还有关于大图片的加载相关工具类