OnTouchEvent+Matrix圖片縮放簡單實現
準備
我們需要一個Activity以及對應的佈局檔案,當然也可以用fragment;
在佈局檔案中,新增一個放置圖片的ImageView控制元件,並設定好圖片和ID。
這是我的Activity和佈局檔案,以及設定好圖片和ID的ImageView控制元件:

圖片描述
開始
在Activity中繫結控制元件(這裡我用的butterknife快速繫結),建立三個常量,表示手指的三種狀態:抬起,縮放,拖拽;建立一個變數,記錄這三種狀態:
@BindView(R.id.img) ImageView img; private final int NONE=0;//抬起 private final int ZOOM=1;//縮放 private final int DRAG=2;//拖拽 private int status=NONE;//儲存當前狀態 private double lastDis;
再建立兩個PointF物件和兩個Matrix物件,幹什麼用的,已經寫在註釋裡面了:
PointF midPoint=new PointF();//當兩根手指放下時,記錄兩根手指中點座標 PointF startPoint=new PointF();//當一根手指放下時,記錄當前座標 Matrix matrix=new Matrix();//用於變換圖片的矩陣 Matrix savedMatrix=new Matrix();//用於儲存矩陣資訊
在onCreate()方法中設定圖片的縮放方式為矩陣縮放:
img.setScaleType(ImageView.ScaleType.MATRIX);//設定圖片的縮放方式
重寫onTouchEvent()方法:
/** * 當單指放下時,用先用matrix儲存圖片資訊,再將matrix的值賦給savedMatrix,startPoint記錄當前座標,status記錄當前狀態; * 當雙指放下時,lastDis記錄兩指之間的距離,將matrix當前值付給savedMatrix,midPoint記錄兩指的中點座標,status記錄當前狀態。 * * 當手指開始移動時,根據status的值決定移動還是縮放; * 如果是移動,將savedMatrix的值賦給matrix,呼叫matrix.postTranslate()方法,更改matrix的值; * 如果是縮放,獲取當前手指之間的距離,同樣將savedMatrix的值賦給matrix,呼叫matrix.postScale()方法更改matrix的值。 * * 最後再switch語句外邊,呼叫img.setImageMatrix()變換圖片。 * @param event * @return */ @Override public boolean onTouchEvent(MotionEvent event) { switch (MotionEvent.ACTION_MASK&event.getAction()){ case MotionEvent.ACTION_DOWN: matrix.set(img.getImageMatrix()); savedMatrix.set(matrix); startPoint.set(event.getX(),event.getY()); status=DRAG; break; case MotionEvent.ACTION_POINTER_DOWN: lastDis=getFingerDis(event); savedMatrix.set(matrix); midPoint=getMidPoint(event); status=ZOOM; break; case MotionEvent.ACTION_MOVE: switch (status){ case DRAG: matrix.set(savedMatrix); matrix.postTranslate(event.getX()-startPoint.x,event.getY()-startPoint.y); break; case ZOOM: double curDis=getFingerDis(event); float scaleMul= (float) (curDis/lastDis); matrix.set(savedMatrix); matrix.postScale(scaleMul,scaleMul,midPoint.x,midPoint.y); break; } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: status=NONE; break; } img.setImageMatrix(matrix);//讓圖片根據矩陣資訊變化(平移或縮放) return true; }
獲取兩點間距離的方法:
private double getFingerDis(MotionEvent e){ double disX=Math.abs(e.getX(0)-e.getX(1)); double disY=Math.abs(e.getY(0)-e.getY(1)); return Math.sqrt(disX*disX+disY*disY); }
獲取兩點間中點座標的方法:
private PointF getMidPoint(MotionEvent e){ float midX=(e.getX(0)+e.getX(1))/2; float midY=(e.getY(0)+e.getY(1))/2; return new PointF(midX,midY); }