OnTouchListener與OnGestureListener的區別

Android事件處理機制是基於Listener實現的,好比觸摸屏相關的事件,是經過OnTouchListener實現的;而手勢是經過OnGestureListener實現的,那麼這二者有什麼關聯呢?this

OnTouchListener

OnTouchListener接口中包含一個onTouch()方法,直接看一個例子:spa

public class MainActivity extends Activity implements OnTouchListener {
	public void onCreate(Bundle outState) {
    	super.onCreate(outState);
    	setContentView(R.layout.main);
    	TextView tv = (TextView) findViewById(R.id.tv);
    	tv.setOnTouchListener(this);
    }

    public boolean onTouch(View v, MotionEvent event) {
    	Toast.makeText(this,  "Touch Touch", Toast.LENGTH_SHORT).show();
		return false ; 
    }
}

咱們能夠經過MotionEvent的getAction()方法來獲取Touch事件的類型,包括 ACTION_DOWN(按下觸摸屏), ACTION_MOVE(按下觸摸屏後移動受力點), ACTION_UP(鬆開觸摸屏)和ACTION_CANCEL(不會由用戶直接觸發)。藉助對於用戶不一樣操做的判斷,結合getRawX()、 getRawY()、getX()和getY()等方法來獲取座標後,咱們能夠實現諸如拖動某一個按鈕,拖動滾動條等功能。code

能夠看到OnTouchListener只能監聽到三種觸摸事件,即按下,移動,鬆開,若是想要監聽到雙擊、滑動、長按等複雜的手勢操做,這個時候就必須得用到OnGestureListener了。接口

OnGestureListener

接着上面的例子,此次加入手勢監聽:事件

public class MainActivity extends Activity implements OnTouchListener, OnGestureListener {
	private  GestureDetector mGestureDetector; 

	public void onCreate(Bundle outState) {
    	super.onCreate(outState);
    	setContentView(R.layout.main);

    	mGestureDetector = new GestureDetector(this);
    	TextView tv = (TextView) findViewById(R.id.tv);
    	tv.setOnTouchListener(this);
    }

    public boolean onTouch(View v, MotionEvent event) {
    	return mGestureDetector.onTouchEvent(event);
    }

    // 用戶輕觸觸摸屏,由1個MotionEvent ACTION_DOWN觸發  
    public boolean onDown(MotionEvent arg0) {
		Log.i("MyGesture", "onDown");
		Toast.makeText(this, "onDown", Toast.LENGTH_SHORT).show();      
		return true;
	}

	// 用戶輕觸觸摸屏,還沒有鬆開或拖動,由一個1個MotionEvent ACTION_DOWN觸發, 注意和onDown()的區別,強調的是沒有鬆開或者拖動的狀態
	public void onShowPress(MotionEvent e) {
		Log.i("MyGesture",  "onShowPress");           
		Toast.makeText(this, "onShowPress", Toast.LENGTH_SHORT).show();
	}

	// 用戶(輕觸觸摸屏後)鬆開,由一個1個MotionEvent ACTION_UP觸發

	public   boolean  onSingleTapUp(MotionEvent e) {
		Log.i("MyGesture", "onSingleTapUp");
		Toast.makeText(this, "onSingleTapUp", Toast.LENGTH_SHORT).show();
		return true;
	}

	// 用戶按下觸摸屏、快速移動後鬆開,由1個MotionEvent ACTION_DOWN, 多個ACTION_MOVE, 1個ACTION_UP觸發        

	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {    
		Log.i("MyGesture", "onFling");
		Toast.makeText(this, "onFling", Toast.LENGTH_LONG).show();     
		return true;
	}

  	// 用戶按下觸摸屏,並拖動,由1個MotionEvent ACTION_DOWN, 多個ACTION_MOVE觸發

	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {            
		Log.i("MyGesture", "onScroll");
 		Toast.makeText(this, "onScroll", Toast.LENGTH_LONG).show();
		return true;
 	}

  	// 用戶長按觸摸屏,由多個MotionEvent ACTION_DOWN觸發

	public   void  onLongPress(MotionEvent e) {
		Log.i("MyGesture", "onLongPress");
		Toast.makeText(this, "onLongPress", Toast.LENGTH_LONG).show();
 	}
}

本示例中,用到了OnGestureListener接口的onScroll()和OnFling()方法,涉及到了Android系統座標及觸摸MotionEvent e1和e二、速度velocityX、velocityY等值,那麼這裏就順便補充下Android屏幕座標系以下圖:ci

 

(1)MotionEvent中 e1是手指第一次按上屏幕的起點,e2是擡起手指離開屏幕的終點,根據上圖Android屏幕座標系可知:get

手指向右滑動,終點(e2)在起點(e1)的右側,有e2.getX() - e1.getX() 大於0 手指向左滑動,終點(e2)在起點(e1)的左側,有e2.getX() - e1.getX() 小於0 手指向下滑動,終點(e2)在起點(e1)的下側,有e2.getY() - e1.getY() 大於0 手指向上滑動,終點(e2)在起點(e1)的上側,有e2.getY() - e1.getY() 小於0it

(2)onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)io

distanceX,是先後兩次call的X距離,不是e2與e1的水平距離 distanceX,是先後兩次call的Y距離,不是e2與e1的垂直距離 具體數值的方向,請詳見上圖(中)event

(3)onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)

velocityX,是X軸的每秒速度 velocityY,是Y軸的每秒速度 具體數值的方向,請詳見上圖(右) 仔細觀察能夠發現:velocityX、velocityY的方向與distanceX、distanceY方向正好相反

相關文章
相關標籤/搜索