GestureDetector 可以使用 MotionEvents 檢測各種手勢和事件突想。
這個類只能用于檢測觸摸事件的 MotionEvent
GestureDetector有三個內(nèi)部接口鲁驶,兩個內(nèi)部類
三個核心接口
OnGestureListener
OnDoubleTapListener
OnContextClickListener
他們都是起到監(jiān)聽器的作用
兩個內(nèi)部類:
- SimpleOnGestureListener
注意:SimpleOnGestureListener繼承了GestureDetector的三個內(nèi)部接口
- GestureHandler
處理GestureDetector類的數(shù)據(jù)
構(gòu)造方法
GestureDetector自帶了五個構(gòu)造方法,但是有兩個被廢棄了
public GestureDetector(Context context, OnGestureListener listener)
public GestureDetector(Context context, OnGestureListener listener, Handler handler)
public GestureDetector(Context context, OnGestureListener listener, Handler handler, boolean unused){this(context, listener, handler);}
因為第三個調(diào)用第二個草描,所以只要關(guān)注前面兩個就行了
我們發(fā)現(xiàn)第二個構(gòu)造方法中多了一個Handler變量
一般來說,不會使用這個構(gòu)造方法
但是因為GestureDetector中的數(shù)據(jù)是給GestureHandler內(nèi)部類進行處理庸蔼,這個類會使用Handle糙臼,由Handler的知識知道,創(chuàng)建Handler必須有Looper禾怠,但是在一些新開的線程中沒有創(chuàng)建Looper,所以我們需要傳入一個帶了Looper的Handler變量贝搁,否則吗氏,GestureDetector對象會創(chuàng)建失敗
SimpleOnGestureListener類的方法:
//下面的6個方法繼承自OnGestureListener
public boolean onSingleTapUp( MotionEvent e)
當用戶單擊時觸發(fā)
public void onLongPress (MotionEvent e )
當用戶手指在長按屏幕時觸發(fā)
public boolean onScroll (MotionEvent e1 , MotionEvent e2 ,float distanceX , float distanceY)
當用戶手指在屏幕上拖動時觸發(fā)
后面兩個變量時在X,Y上移動的距離
public boolean onFling ( MotionEvent e1 ,MotionEvent e2 , float velocityX , float velocityY)
當用戶手指拖動后,手指離開屏幕時觸發(fā)
這個方法常用來使手指離開后頁面仍然可以滑動(速度慢慢變欣啄妗)
后兩個變量表示手指在X,Y兩個方向上的速度
public void onShowPress (MotionEvent e)
當用戶手指按下弦讽,但沒有移動時觸發(fā)該方法
public boolean onDown ( MotionEvent e)
當按下時觸發(fā)該方法,所有手勢第一個必定觸發(fā)該方法
//下面的三個方法繼承自OnDoubleTapListener
public boolean onDoubleTap (MotionEvent e)
當用戶雙擊時觸發(fā)
public boolean onDoubleTapEvent (MotionEvent e)
在雙擊事件確定發(fā)生時會對第二次按下產(chǎn)生的 MotionEvent 信息進行回調(diào)膀哲。
public boolean onSingleTapConfirmed ( MotionEvent e)
當單擊事件確定后進行回調(diào)
//下面的這個方法繼承自ContextClickListener
onContextClick ( MotionEvent e)
用于檢測外部設備上的按鈕是否按下的往产,例如藍牙觸控筆上的按鈕,一般情況下某宪,忽略即可仿村。
如果偵聽 onContextClick(MotionEvent),
則必須在 View 的onGenericMotionEvent(MotionEvent)中
調(diào)用 GestureDetector OnGenericMotionEvent(MotionEvent)兴喂。
手勢的常用事件
按下
public boolean onDown (MotionEvent e)
按下是所以手勢必定有的動作
所以無論什么手勢蔼囊,第一個調(diào)用的方法就是onDown
注意:
GestureDetector的點擊對圖片焚志,按鈕等無用
為了解決這個問題,我們可以
- onDown返回true(根據(jù)響應中的先回調(diào)畏鼓,后監(jiān)聽)
- 圖片等的xml文件中設置android:Clickable="true"
單擊:
public boolean onSingleTapUp( MotionEvent e)
public boolean onSingleTapConfirmed ( MotionEvent e)
這兩個方法都可以響應到單擊事件酱酬,但是他們之間還是有區(qū)別的
當我們同時在監(jiān)聽器中覆寫這兩個方法,并且進行單擊事件
我們會發(fā)現(xiàn)當進行單擊事件的時候云矫,這幾個方法響應的順序是這樣的
onDown() -> onSingleTapUp() -> onSingleCofirmed()
首先onDown()必定是第一個執(zhí)行的膳沽,但是會發(fā)現(xiàn)onSingleTapUp在onSingleComfirmed之前執(zhí)行
我查閱了相關(guān)文檔,發(fā)現(xiàn)他們雖然同樣響應的是當手指離開屏幕的活動让禀,但是onSingleTapUp是立即執(zhí)行挑社,而onSingleComfirmed卻要在離開后300ms后才執(zhí)行 ,這樣的目的是確認我們進行的是單擊事件(為了防止我們在300ms內(nèi)再次進行單擊事件)堆缘,所以他們的名字分別是Up和Comfirmed
所以滔灶,在設置雙擊事件時,最好使用onSingleComfirmed()吼肥,進行雙擊時不會回調(diào)單擊方法
雙擊
public boolean onDoubleTap (MotionEvent e)
public boolean onDoubleTapEvent (MotionEvent e)
這兩個方法都可以響應雙擊事件录平,為了驗證他們的區(qū)別,我們同樣在一個響應器中覆寫這兩個方法缀皱,并且進行雙擊事件(我們這里單擊事件使用onSingleComfirmed)
我們使用Log.e()把方法響應的順序弄出來斗这,發(fā)現(xiàn)他們規(guī)律很神奇
onDown() -> onDoubleTap() -> onDoubleTapEvent() -> onDown()-> onDoubleTapEvent() ->onDoubleTapEvent()(不定數(shù)目個)
然后我在onDoubleTapEvent()中吧MotionEvent e 輸出,
然后方法響應的順序變成:
onDown() -> onDoubleTap() -> onDoubleTapEvent() -> onDown()-> onDoubleTapEvent() Down -> onDoubleTapEvent()Move(不定數(shù)目個) ->onDoubleTapEvent() Up
我們對以上信息進行分析:
DoubleTap在DoubleTapEvent前面執(zhí)行,但是根據(jù)DoubleTapEvent的第一個MotionEvent是Down啤斗,所以判斷雙擊的響應條件是在第一次單擊后的300ms內(nèi)按下手指
我們又嘗試在雙擊后手指不離開屏幕表箭,可見隨時間的延長,Move也變得更多钮莲,
由此判斷免钻,onDoubleTapEvent是實時回調(diào)的,并且是用來檢測MotionEvent
長按
public void onShowPress (MotionEvent e)
public void onLongPress (MotionEvent e)
這次我們在響應器中覆寫所有方法崔拥,進行長按操作
發(fā)現(xiàn)方法響應的順序為:
onDown -> onShowPress -> onLongPress
也就是說极舔,在長按時,onShowPress在onLongPress前面執(zhí)行
滑動/拖動
public void onScroll (MotionEvent e)
public void onFling (MotionEvent e)
同樣链瓦,我們覆寫所有方法拆魏,進行滑動操作,
發(fā)現(xiàn)方法的響應順序為
onDown -> onScroll -> 不定量個onScroll ->onScroll -> onFiling
由此可見,在滑動/拖動過程中慈俯,不斷調(diào)用onScroll渤刃,最后調(diào)用onFiling
當然,Android自帶的手勢不能完全滿足我們的需求贴膘,于是Android提供了自建手勢的方法卖子,這些內(nèi)容將在下一篇博客中陳述