Android多點觸控---Matrix圖片隨意的放大縮小,拖動

 Android多點觸控 Matrix圖片隨意的放大縮小,拖動

 

一、新建一個項目AnroidImageDragAndZoom,並準備一張照片放在res/drawable-hdpi目錄下,如下圖所示:



 

 

二、設置應用的UI界面,在main.xml中設置:



 

三、MainActivity.java中實現具體的需求

package com.example.anroidimagedragandzoom;

import android.app.Activity;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.os.Bundle;
import android.util.FloatMath;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;
/**
 * 枚舉方式實現事件
 * @author miaowei
 *
 */
public class MainActivityEnum extends Activity{

	private enum Type{
		/**
		 * 記錄是拖放照片模式還是放大縮小照片模式
		 */
		MODE,
		/**
		 * 拖放照片模式
		 */
		MODE_DRAG,
		/**
		 * 放大縮小照片模式
		 */
		MODE_ZOOM
	}
	
	private ImageView imageView;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		imageView = (ImageView)findViewById(R.id.imageView);
		imageView.setOnTouchListener(touchListener);
	}
	
	
	private class MainEventEnmu extends EventInfoBase<Enum<?>>{
		
		@Override
		public void setEvent(Enum<?> event) {
			
			super.setEvent(event);
		}
	}
	private OnTouchListener touchListener  = new OnTouchListener() {
		/**
		 * 用於記錄開始時候的座標位置
		 */
		private PointF startPoint = new PointF();
		/**
		 * 用於記錄拖拉圖片移動的座標位置
		 */
		private Matrix matrix = new Matrix();
		/**
		 * 用於記錄圖片要進行拖拉時候的座標位置
		 */
		private Matrix currentMatrix = new Matrix();
		/**
		 * 兩個手指的開始距離
		 */
	    private float startDis;
	    /**
	     * 兩個手指的中間點
	     */
	    private PointF midPointF;
	    MainEventEnmu mainEventEnmu = new MainEventEnmu();
		@Override
		public boolean onTouch(View v, MotionEvent event) {
		
			//通過與運算保留最後八位 MotionEvent.ACTION_MASK = 255
			switch (event.getAction() & MotionEvent.ACTION_MASK) {
			//手指壓下屏幕
			case MotionEvent.ACTION_DOWN:
				
				mainEventEnmu.setEvent(Type.MODE_DRAG);
				
				//記錄ImageView當前的移動位置
				currentMatrix.set(imageView.getImageMatrix());
				startPoint.set(event.getX(), event.getY());
				break;
				//手指在屏幕上移動,改事件會被不斷觸發
			case MotionEvent.ACTION_MOVE:
				//拖拉圖片
				if (mainEventEnmu.getEvent() == Type.MODE_DRAG) {
					//得到X軸的移動距離
					float dx = event.getX() - startPoint.x;
					//得到Y軸的移動距離
					float dy = event.getY() - startPoint.y;
					//在沒有移動之前的位置上進行移動
					matrix.set(currentMatrix);
					matrix.postTranslate(dx, dy);
				} //放大縮小圖片
				else if (mainEventEnmu.getEvent() == Type.MODE_ZOOM) {
					//結束距離
					float endDis = distance(event);
					// 兩個手指併攏在一起的時候像素大於10
					if (endDis > 10f) {
						// 得到縮放倍數
						float scale = endDis / startDis;
						
						matrix.set(currentMatrix);
						matrix.postScale(scale, scale,midPointF.x,midPointF.y);
					}
				}
				break;
				// 手指離開屏幕
			case MotionEvent.ACTION_UP:
				//當觸點離開屏幕,但是屏幕上還有觸點(手指),多點
			case MotionEvent.ACTION_POINTER_UP:
				mainEventEnmu.setEvent(Type.MODE);
				break;
				// 當屏幕上已經有觸點(手指),再有一個觸點壓下屏幕,多點
			case MotionEvent.ACTION_POINTER_DOWN:
				mainEventEnmu.setEvent(Type.MODE_ZOOM);
				/** 計算兩個手指間的距離 */
				startDis = distance(event);
				// 兩個手指併攏在一起的時候像素大於10
				if (startDis > 10f) {
					
					midPointF = mid(event);
					 //記錄當前ImageView的縮放倍數
					currentMatrix.set(imageView.getImageMatrix());
				}
				break;
			}
			imageView.setImageMatrix(matrix);
			return true;
		}
	};
		
	/**
	 * 計算兩個手指間的距離
	 * @param event
	 * @return
	 */
	private float distance(MotionEvent event){
		
		float dx = event.getX(1) - event.getX(0);
		float dy = event.getY(1) - event.getY(0);
		//使用勾股定理返回兩點神之間的距離
		return FloatMath.sqrt(dx * dx + dy * dy);
	}
	/**
	 * 計算兩個手指間的中間點
	 * @return
	 */
	private PointF mid(MotionEvent evntEvent){
		
		float midX = (evntEvent.getX(1) + evntEvent.getX(0));
		float midY = (evntEvent.getY(1) + evntEvent.getY(0));
		
		return new PointF(midX, midY);
		
	}
	
	
}

 Activity需要實現一個OnTouchListener的方法,來設置ImageView的偵聽屬性,該接口位於android.view.View.OnTouchListener。

實現onTouch(View view, MotionEvent event)的方法,就可以獲取觸屏的感應事件了。

在該事件中,有兩個參數可以用來獲取對觸摸的控制,這兩個參數分別爲:MotionEvent.getAction()和MotionEvent.ACTION_MASK,前者用於對單點觸控進行操作,後者用於對多點觸控進行操作,相應地,我們可以通過Android Developers’ Reference看到,對於單點觸控,我們由MotionEvent.getAction()可以得到以下幾種事件:ACTION_DOWN、ACTION_UP,而對於多點觸控,由MotionEvent.ACTION_MASK,我們可以得到:ACTION_POINTER_DOWN、ACTION_POINTER_UP,都是MotionEvent中的常量,可以直接調用。而有些常量則是單點和多點共用的,如:ACTION_MOVE,因此在按下時,我們必須標記單點與多點觸控的區別。

 

附件中有采用枚舉標識實現方式

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章