從現在開始做學習博客,記錄自己的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貼上,這裏面還有關於大圖片的加載相關工具類