Android--事件響應--觸控屏幕(演示類庫)

轉載於:

Android觸控屏幕Gesture(GestureDetector和SimpleOnGestureListener的使用教程)

1、當用戶觸摸屏幕的時候,會產生許多手勢,例如down,up,scroll,filing等等,我們知道View類有個View.OnTouchListener內部接口,通過重寫他的onTouch(View v, MotionEvent event)方法,我們可以處理一些touch事件,但是這個方法太過簡單,如果需要處理一些複雜的手勢,用這個接口就會很麻煩(因爲我們要自己根據用戶觸摸的軌跡去判斷是什麼手勢)Android sdk給我們提供了GestureDetector(Gesture:手勢Detector:識別)類,通過這個類我們可以識別很多的手勢,主要是通過他的onTouchEvent(event)方法完成了不同手勢的識別。雖然他能識別手勢,但是不同的手勢要怎麼處理,應該是提供給程序員實現的,因此這個類對外提供了兩個接口:OnGestureListener,OnDoubleTapListener,還有一個內部類SimpleOnGestureListener,SimpleOnGestureListener類是GestureDetector提供給我們的一個更方便的響應不同手勢的類,這個類實現了上述兩個接口(但是所有的方法體都是空的),該類是static class,也就是說它實際上是一個外部類。程序員可以在外部繼承這個類,重寫裏面的手勢處理方法。

通過GestureDetector的構造方法可以將SimpleOnGestureListener對象傳遞進去,這樣GestureDetector能處理不同的手勢了。

2.、具體用法:

/**
 * 當我們捕捉到Touch操作的時候,如何識別出用戶的Gesture?這裏我們需要GestureDetector.OnGestureListener接口的幫助
 * 
 * @author HB
 */
public class MySurfaceView extends SurfaceView implements OnGestureListener,
		OnTouchListener, Callback {
	GestureDetector gd;
	Context context;

	public MySurfaceView(Context context) {
		super(context);
		this.context = context;
		setFocusable(true);
		requestFocus();
		this.setLongClickable(true);
		this.setOnTouchListener(this);
		setFocusable(true);
		gd = new GestureDetector(new MySimpleGesture());// 這裏或者可以直接傳遞this參數,因爲本類已經繼承了OnGestureListener接口,也可以把new
														// MySimpleGesture(),它繼承了SimpleOnGestureListener類;,兩種方法都可以,只是把兩種方法歸在一個裏面,方便學習;
														// 。實惠屏幕觸控事件;
		gd.setIsLongpressEnabled(true);
		// TODO Auto-generated constructor stub
	}

	// 用戶輕觸觸摸屏,由1個MotionEvent ACTION_DOWN觸發
	@Override
	public boolean onDown(MotionEvent e) {
		// TODO Auto-generated method stub
		System.out.println("onDown");
		return false;
	}

	/*
	 * 用戶輕觸觸摸屏,尚未鬆開或拖動,由一個1個MotionEvent ACTION_DOWN觸發
	 * 注意和onDown()的區別,強調的是沒有鬆開或者拖動的狀態 (單擊沒有鬆開或者移動時候就觸發此事件,再觸發onLongPress事件)
	 */
	@Override
	public void onShowPress(MotionEvent e) {
		// TODO Auto-generated method stub
		System.out.println("onShowPress");
	}

	// 用戶(輕觸觸摸屏後)鬆開,由一個1個MotionEvent ACTION_UP觸發
	@Override
	public boolean onSingleTapUp(MotionEvent e) {
		// TODO Auto-generated method stub
		System.out.println("onSingleTopUp");
		return false;
	}

	// 用戶按下觸摸屏,並拖動,由1個MotionEvent ACTION_DOWN, 多個ACTION_MOVE觸發
	@Override
	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
			float distanceY) {
		System.out.println("onScroll");
		// TODO Auto-generated method stub
		return false;
	}

	// 用戶長按觸摸屏,由多個MotionEvent ACTION_DOWN觸發
	@Override
	public void onLongPress(MotionEvent e) {
		// TODO Auto-generated method stub
		System.out.println("onLongPress");
	}

	/*
	 * 用戶按下觸摸屏、快速移動後鬆開,由1個MotionEvent ACTION_DOWN, 多個ACTION_MOVE,
	 * 1個ACTION_UP觸發(non-Javadoc)
	 * Fling事件的處理代碼:除了第一個觸發Fling的ACTION_DOWN和最後一個ACTION_MOVE中包含的座標等信息外
	 * ,我們還可以根據用戶在X軸或者Y軸上的移動速度作爲條件
	 * 比如下面的代碼中我們就在用戶移動超過100個像素,且X軸上每秒的移動速度大於200像素時才進行處理。
	 * 
	 * @see android.view.GestureDetector.OnGestureListener#onFling(android.view.
	 * MotionEvent, android.view.MotionEvent, float, float)
	 * 這個例子中,tv.setLongClickable( true )是必須的,因爲
	 * 只有這樣,view才能夠處理不同於Tap(輕觸)的hold(即ACTION_MOVE,或者多個ACTION_DOWN)
	 * ,我們同樣可以通過layout定義中的android:longClickable來做到這一點
	 */
	@Override
	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
			float velocityY) {
		// TODO Auto-generated method stub
		System.out.println("onFling");
		// 參數解釋:
		// e1:第1個ACTION_DOWN MotionEvent
		// e2:最後一個ACTION_MOVE MotionEvent
		// velocityX:X軸上的移動速度,像素/秒
		// velocityY:Y軸上的移動速度,像素/秒

		// 觸發條件 :
		// X軸的座標位移大於FLING_MIN_DISTANCE,且移動速度大於FLING_MIN_VELOCITY個像素/秒
		final int FLING_MIN_DISTANCE = 100, FLING_MIN_VELOCITY = 200;
		if (e1.getX() - e2.getX() > FLING_MIN_DISTANCE
				&& Math.abs(velocityX) > FLING_MIN_VELOCITY) {
			// Fling left
			Log.i("MyGesture", "Fling left");
			Toast.makeText(context, "Fling Left", Toast.LENGTH_SHORT).show();
		} else if (e2.getX() - e1.getX() > FLING_MIN_DISTANCE
				&& Math.abs(velocityX) > FLING_MIN_VELOCITY) {
			// Fling right
			Log.i("MyGesture", "Fling right");
			Toast.makeText(context, "Fling Right", Toast.LENGTH_SHORT).show();
		}
		return true;
	}

	/**
	 * 當發行屏幕觸控事件的時候,首先出發此方法,再通過此方法,監聽具體的整件
	 * 在onTouch()方法中,我們調用GestureDetector的onTouchEvent
	 * ()方法,將捕捉到的MotionEvent交給GestureDetector 來分析是否有合適的callback函數來處理用戶的手勢
	 */
	@Override
	public boolean onTouch(View v, MotionEvent event) {
		// TODO Auto-generated method stub
		System.out.println("onTouch");
		return gd.onTouchEvent(event);
	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		// TODO Auto-generated method stub

	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
		// TODO Auto-generated method stub

	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		// TODO Auto-generated method stub

	}

	/**
	 * SimpleOnGestureListener implements GestureDetector.OnDoubleTapListener,
	 * GestureDetector.OnGestureListener
	 */
	private class MySimpleGesture extends SimpleOnGestureListener {
		// 雙擊的第二下Touch down時觸發
		public boolean onDoubleTap(MotionEvent e) {
			Log.i("MyGesture", "onDoubleTap");
			return super.onDoubleTap(e);
		}

		// 雙擊的第二下Touch down和up都會觸發,可用e.getAction()區分
		public boolean onDoubleTapEvent(MotionEvent e) {
			Log.i("MyGesture", "onDoubleTapEvent");
			return super.onDoubleTapEvent(e);
		}

		// Touch down時觸發
		public boolean onDown(MotionEvent e) {
			Log.i("MyGesture", "onDown");
			return super.onDown(e);
		}

		// Touch了滑動一點距離後,up時觸發
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
				float velocityY) {
			Log.i("MyGesture", "onFling");
			return super.onFling(e1, e2, velocityX, velocityY);
		}

		// Touch了不移動一直Touch down時觸發
		public void onLongPress(MotionEvent e) {
			Log.i("MyGesture", "onLongPress");
			super.onLongPress(e);
		}

		// Touch了滑動時觸發
		public boolean onScroll(MotionEvent e1, MotionEvent e2,
				float distanceX, float distanceY) {
			Log.i("MyGesture", "onScroll");
			return super.onScroll(e1, e2, distanceX, distanceY);
		}

		/*
		 * Touch了還沒有滑動時觸發 (1)onDown只要Touch Down一定立刻觸發 (2)Touch
		 * Down後過一會沒有滑動先觸發onShowPress再觸發onLongPress So: Touch Down後一直不滑動,onDown
		 * -> onShowPress -> onLongPress這個順序觸發。
		 */
		public void onShowPress(MotionEvent e) {
			Log.i("MyGesture", "onShowPress");
			super.onShowPress(e);
		}

		/*
		 * 兩個函數都是在Touch Down後又沒有滑動(onScroll),又沒有長按(onLongPress),然後Touch Up時觸發
		 * 點擊一下非常快的(不滑動)Touch Up: onDown->onSingleTapUp->onSingleTapConfirmed
		 * 點擊一下稍微慢點的(不滑動)Touch Up://確認是單擊事件觸發
		 * onDown->onShowPress->onSingleTapUp->onSingleTapConfirmed
		 */
		public boolean onSingleTapConfirmed(MotionEvent e) {
			Log.i("MyGesture", "onSingleTapConfirmed");
			return super.onSingleTapConfirmed(e);
		}

		public boolean onSingleTapUp(MotionEvent e) {
			Log.i("MyGesture", "onSingleTapUp");
			return super.onSingleTapUp(e);
		}
	}
}


結果:

1、當單擊屏幕的時候,輸出:


2、當單擊等一會再鬆開時候輸出(觸觸摸屏,比單擊慢):


3、當用戶按住不放的時候,輸出:


4、當用戶按住不放,拖動鼠標的時候輸出:


5、當用戶按住不放,快速拖動鼠標的時候:


6、當用戶雙擊的時候(觀察與單擊的區別---onDubleTab在第二次按下Down的時候纔出發,說明 是雙擊事件在onDown事件之前;):

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