手機屏幕事件的處理方法onTouchEvent。該方法在View類中的定義,而且全部的View子類所有重寫了該方法,應用程序能夠經過該方法處理手機屏幕的觸摸事件。該方法的簽名以下所示。android
public boolean onTouchEvent(MotionEvent event)
參數event:參數event爲手機屏幕觸摸事件封裝類的對象,其中封裝了該事件的全部信息,例如觸摸的位置、觸摸的類型以及觸摸的時間等。該對象會在用戶觸摸手機屏幕時被建立。函數
返回值:該方法的返回值機理與鍵盤響應事件的相同,一樣是當已經完整地處理了該事件且不但願其餘回調方法再次處理時返回true,不然返回false。this
該方法並不像以前介紹過的方法只處理一種事件,通常狀況下如下三種狀況的事件所有由onTouchEvent方法處理,只是三種狀況中的動做值不一樣。spa
屏幕被按下:當屏幕被按下時,會自動調用該方法來處理事件,此時MotionEvent.getAction()的值爲MotionEvent.ACTION_DOWN,若是在應用程序中須要處理屏幕被按下的事件,只需從新該回調方法,而後在方法中進行動做的判斷便可。code
屏幕被擡起:當觸控筆離開屏幕時觸發的事件,該事件一樣須要onTouchEvent方法來捕捉,而後在方法中進行動做判斷。當MotionEvent.getAction()的值爲MotionEvent.ACTION_UP時,表示是屏幕被擡起的事件。對象
在屏幕中拖動:該方法還負責處理觸控筆在屏幕上滑動的事件,一樣是調用MotionEvent.getAction()方法來判斷動做值是否爲MotionEvent.ACTION_MOVE再進行處理。blog
Android Touch Screen 與傳統Click Touch Screen不一樣,會有一些手勢(Gesture),例如Fling,Scroll等等。這些Gesture會使用戶體驗大大提高。
Android中的Gesture識別(detector)是經過GestureDetector.OnGestureListener接口實現的。
首先,Android事件處理機制是基於Listener實現的,好比觸摸屏相關的事件,就是經過onTouchListener實現;
其次,全部View的子類均可以經過setOnTouchListener()、setOnKeyListener()等方法來添加對某一類事件的Listener;
第三,Listener通常會以Interface的方式來提供,其中包含一個或多個abstract方法,咱們須要實現這些方法來完成 onTouch()、onKey()等操做。這樣,程序即可以在特定的事件被dispatch到該view的時候,經過callback函數給予適當的響 應。接口
1. Touch Screen Click舉例事件
public class MyGesture extends Activity implements OnTouchListener { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); 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()等方法來獲取座標後,咱們能夠實現諸如拖動某一個按鈕,拖動滾動條等功能。2. 當咱們捕捉到Touch操做的時候,如何識別出用戶的Gesture?這裏咱們須要GestureDetector.OnGestureListener接口的幫助,代碼以下:ci
public class MyGesture extends Activity implements OnTouchListener, OnGestureListener { private GestureDetector mGestureDetector; public MyGesture() { mGestureDetector = new GestureDetector(this); } public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TextView tv = (TextView) findViewById(R.id.tv); tv.setOnTouchListener(this); tv.setFocusable(true); tv.setClickable(true); tv.setLongClickable(true); mGestureDetector.setIsLongpressEnabled(true); } /* * *在onTouch()方法中,咱們調用GestureDetector的onTouchEvent()方法, * 將捕捉到的MotionEvent交給GestureDetector * 來分析是否有合適的callback函數來處理用戶的手勢 */ 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(); } }
3. Fling事件的處理代碼:除了第一個觸發Fling的ACTION_DOWN和最後一個ACTION_MOVE中包含的座標等信息外,咱們還能夠根據用 戶在X軸或者Y軸上的移動速度做爲條件。好比下面的代碼中咱們就在用戶移動超過100個像素,且X軸上每秒的移動速度大於200像素時才進行處理。
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // 參數解釋: // 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(this, "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(this, "Fling Right", Toast.LENGTH_SHORT).show(); } return false; }
這個例子中,tv.setLongClickable(true)是必須的,由於 只有這樣,view纔可以處理不一樣於Tap(輕觸)的hold(即ACTION_MOVE,或者多個ACTION_DOWN),咱們一樣能夠經過layout定義中的android:longClickable來作到這一點.