觸控事件與手勢監聽--Android GestureDetector詳解
目錄
- 事件監聽的方法
- GestureDetector類
- GestureDetector使用方法
- GesturetDetector.OnGestureListener 介面
- GesttureDetector.OnDoubleTapListener 介面
- GesttureDetector.SimpleOnGestureListener 類
1:事件監聽的方法
在android應用層上主要有兩個層面的觸控事件監聽,一個是Activity層,另一個是View層。方法主要有三種:
第一是Activity中重寫父類中的public boolean onTouchEvent(MotionEvent event)方法;
@Override
public boolean onTouchEvent(MotionEvent event) {
return super.onTouchEvent(event);
}
第二個是重寫View類中的GestDetector.OnGestureListener 介面中定義的boolean onTouch(View v, MotionEvent event);
@Override
public boolean onTouch(View v, MotionEvent event) {
return false;
}
第三個是利用GestureDetector.onTouchEvent(event)在View.onTouch方法中來接管事件處理
@Override
public boolean onTouch(View v, MotionEvent event) {
return mGestureDetector.onTouchEvent(event);
}
當view上的事件被分發到view上時觸發onTouch方法的回撥, 如果這個方法返回false時,表示事件處理失敗,該事件就會被傳遞給相應的Activity中的onTouchEvent方法來處理。
如果該方法返回true時,表示該事件已經被onTouch函式處理完,不會上傳到activity中處理。
2:GestureDector類
GestureDector類需要注意以下內容:
- OnGestureListener介面
- OnDoubleTapListener雙擊介面
- SimpleOnGestureListener 類(實現了類內的三個介面)
- onTouchEvent()方法
- setOnDoubleTapListener()雙擊監聽
當螢幕上發生特定的觸控事件,就會去回撥GestureDector.OnGestureListener和GestureDetector.OnDoubleTapListener介面中相應的回撥函式來監測各樣的手勢和事件,並且通知使用者。但是這些觸發函式都沒有具體的實現,我們必須實現這些介面,並重寫這些方法的具體實現。
GestureDetector類中已經為我們定義了一個靜態內部類SimpleOnGestureListener,它實現了OnGestureListener,OnDoubleTapListener,OnContextClickListener介面,定義為
public static class SimpleOnGestureListener implements OnGestureListener, OnDoubleTapListener,
OnContextClickListener
SimpleOnGestureListener類內重寫介面中的所有方法,但是都是空實現,返回的布林值都是false。主要作用是方便我們繼承這個類有選擇的複寫回撥方法,而不是實現介面去重寫所有的方法。
onTouchEvent()方法用來分析傳入的事件,如果匹配的話就去觸發OnGestureListener中相應的回撥方法。
如果要監聽雙擊事件必須呼叫GestureDector.setOnDoubleTapListener()
3:GestureDetector使用方法
第一步:實現OnGestureListener介面中的方法(可以使用匿名內部類或實現了介面的類例項)
內部類形式
class MyGestureListener implements GestureDetector.OnGestureListener {
@Override
public boolean onDown(MotionEvent e) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return false;
}
}
匿名內部類形式
mGestureDetector = new GestureDetector(mContext, new GestureDetector.OnGestureListener() {
@Override
public boolean onDown(MotionEvent e) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return false;
}
});
第二步:建立GestureDetector類的例項,建構函式如下:
public GestureDetector(OnGestureListener listener, Handler handler) {
this(null, listener, handler);
}
public GestureDetector(OnGestureListener listener) {
this(null, listener, null);
}
public GestureDetector(Context context, OnGestureListener listener) {
this(context, listener, null);
}
public GestureDetector(Context context, OnGestureListener listener, Handler handler)
public GestureDetector(Context context, OnGestureListener listener, Handler handler,
boolean unused) {
this(context, listener, handler);
}
前兩個已經廢棄了。
mGestureDetector = new GestureDetector(mContext,new MyGestureListener());
第三步:實現View.OnTouchListener介面,重寫onTouch()方法
第四步:在onTouch()方法中攔截事件處理,將控制權交給GestureDector。
@Override
public boolean onTouch(View v, MotionEvent event) {
return mGestureDetector.onTouchEvent(event);
}
第五步:呼叫控制元件的View.setOnTouchListener()將介面的具體實現的引用傳遞進去或者如果是監聽雙擊的話呼叫GestureDetector .setOnDoubleTapListener()
super.setOnTouchListener(this);
mGestureDetector.setOnDoubleTapListener(new MyGestureListener());
完整程式碼
package com.example.gesturetest;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
/**
* Created by pingkun.huang on 2016/4/16.
*/
public class MyView extends View implements View.OnTouchListener{
private Context mContext;
private GestureDetector mGestureDetector;
private static final String TAG = "MyView";
public MyView(Context context) {
super(context);
initData(context);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
initData(context);
}
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initData(context);
}
private void initData(Context context) {
this.mContext = context;
super.setOnTouchListener(this);
super.setClickable(true);
super.setLongClickable(true);
super.setFocusable(true);
mGestureDetector = new GestureDetector(mContext,new MyGestureListener());
mGestureDetector.setOnDoubleTapListener(new MyGestureListener());
}
/*
* 當該view上的事件被分發到view上時觸發該方法的回撥
* 如果這個方法返回false時,該事件就會被傳遞給Activity中的onTouchEvent方法來處理
* 如果該方法返回true時,表示該事件已經被onTouch函式處理玩,不會上傳到activity中處理
* 該方法屬於View.OnTouchListening介面
* */
@Override
public boolean onTouch(View v, MotionEvent event) {
return mGestureDetector.onTouchEvent(event);
}
/*
*
* 手勢監聽類
* */
class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
public MyGestureListener() {
super();
}
@Override
public boolean onDoubleTap(MotionEvent e) {
Log.e(TAG, "onDoubleTap");
return true;
}
@Override
public boolean onDoubleTapEvent(MotionEvent e) {
Log.e(TAG, "onDoubleTapEvent");
return true;
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
Log.e(TAG, "onSingleTapConfirmed");
return true;
}
@Override
public boolean onContextClick(MotionEvent e) {
Log.e(TAG, "onContextClick");
return true;
}
@Override
public boolean onDown(MotionEvent e) {
Log.e(TAG, "onDown");
return true;
}
@Override
public void onShowPress(MotionEvent e) {
Log.e(TAG, "onShowPress");
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
Log.e(TAG, "onSingleTapUp");
return true;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
Log.e(TAG, "onScroll");
return true;
}
@Override
public void onLongPress(MotionEvent e) {
Log.e(TAG, "onLongPress");
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
Log.e(TAG, "onFling");
return true;
}
}
}
MyView是一個自定義控制元件繼承了View實現了View.OnTouchListener。監聽的方法用的是繼承SimpleOnGestureListener類,重寫了所有方法,僅列印log日誌,具體功能自己根據業務重寫。
4:GesturetDetector.OnGestureListener 介面
class MyGestureListener implements GestureDetector.OnGestureListener {
@Override
/*
*每按一下螢幕立即觸發
* */
public boolean onDown(MotionEvent e) {
return false;
}
@Override
/*
*使用者按下螢幕並且沒有移動或鬆開。主要是提供給使用者一個視覺化的反饋,告訴使用者他們的按下操作已經
* 被捕捉到了。如果按下的速度很快只會呼叫onDown(),按下的速度稍慢一點會先呼叫onDown()再呼叫onShowPress().
* */
public void onShowPress(MotionEvent e) {
}
@Override
/*
*一次單純的輕擊擡手動作時觸發
* */
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
/*
*螢幕拖動事件,如果按下的時間過長,呼叫了onLongPress,再拖動螢幕不會觸發onScroll。拖動螢幕會多次觸發
* @param e1 開始拖動的第一次按下down操作,也就是第一個ACTION_DOWN
* @parem e2 觸發當前onScroll方法的ACTION_MOVE
* @param distanceX 當前的x座標與最後一次觸發scroll方法的x座標的差值。
* @param diastancY 當前的y座標與最後一次觸發scroll方法的y座標的差值。
* */
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return false;
}
@Override
/*
* 長按。在down操作之後,過一個特定的時間觸發
* */
public void onLongPress(MotionEvent e) {
}
@Override
/*
* 按下螢幕,在螢幕上快速滑動後鬆開,由一個down,多個move,一個up觸發
* @param e1 開始快速滑動的第一次按下down操作,也就是第一個ACTION_DOWN
* @parem e2 觸發當前onFling方法的move操作,也就是最後一個ACTION_MOVE
* @param velocityX:X軸上的移動速度,畫素/秒
* @parram velocityY:Y軸上的移動速度,畫素/秒
* */
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return false;
}
}
快按螢幕:onDown
慢按螢幕:onDown–>onShowPress
按下螢幕等待一段時間onDown–>onShowPress–>onLongPress
拖動螢幕:onDown–>onShowPress–>onScroll(多個)–>onFling
快速滑動:onDown–>onScroll(多個)–>onFling
5:GesttureDetector.OnDoubleTapListener 介面
class MyDoubleTapListener implements GestureDetector.OnDoubleTapListener {
@Override
/*
* 單擊事件。用來判定該次點選是單純的SingleTap而不是DoubleTap,如果連續點選兩次就是DoubleTap手勢,
* 如果只點擊一次,系統等待一段時間後沒有收到第二次點選則判定該次點選為SingleTap而不是DoubleTap,
* 然後觸發SingleTapConfirmed事件。觸發順序是:OnDown->OnsingleTapUp->OnsingleTapConfirmed
* 關於onSingleTapConfirmed和onSingleTapUp的一點區別:二者的區別是:onSingleTapUp,只要手擡起就會執行,
* 而對於onSingleTapConfirmed來說,如果雙擊的話,則onSingleTapConfirmed不會執行。
* */
public boolean onSingleTapConfirmed(MotionEvent e) {
return false;
}
@Override
/*
*
* 雙擊事件
* */
public boolean onDoubleTap(MotionEvent e) {
return false;
}
@Override
/*
*
*雙擊間隔中發生的動作。指觸發onDoubleTap以後,在雙擊之間發生的其它動作,包含down、up和move事件
* */
public boolean onDoubleTapEvent(MotionEvent e) {
return false;
}
}
雙擊:onDown–>onSingleTapUp–>onDoubleTap–>onDoubleTapEvent–>onDown–>onDoubleTapEvent
6:GesttureDetector.SimpleOnGestureListener 類
結合了OnGestureListener,OnDoubleTapListener和
OnContextClickListener中的所有方法,可以有選擇的去重寫其中的方法,參考前兩節。