Android 雙擊單擊事件監(jiān)聽(tīng)手勢(shì)檢測(cè)GestureDetector原理及實(shí)現(xiàn)

app我們常用的手勢(shì)有很多的地方,比如右滑關(guān)閉界面等。手勢(shì)控制分為觸發(fā)動(dòng)作(Touch Mechanics,用戶(hù)手指在屏幕上如何動(dòng)作)和觸發(fā)行為(Touch Activities,界面上特定動(dòng)作在特定情境下引發(fā)的結(jié)果)。這是因?yàn)橥瑯拥挠|發(fā)動(dòng)作(如單次觸擊)在不同情境下可能會(huì)帶來(lái)不同的結(jié)果(如輕觸,取消,開(kāi)啟/關(guān)閉指示),同樣單次觸發(fā)行為(如放大)可能是由多種觸發(fā)動(dòng)作(如捏放,雙次觸擊,雙次觸擊拖拽等)實(shí)現(xiàn)。

? ? 一般情況下,我們知道View類(lèi)有個(gè)View.OnTouchListener內(nèi)部接口,通過(guò)重寫(xiě)他的onTouch(View v, MotionEvent event)方法,我們可以處理一些touch事件,但是這個(gè)方法太過(guò)簡(jiǎn)單,如果需要處理一些復(fù)雜的手勢(shì),用這個(gè)接口就會(huì)很麻煩(因?yàn)槲覀円约焊鶕?jù)用戶(hù)觸摸的軌跡去判斷是什么手勢(shì))。

? ? Android sdk給我們提供了GestureDetector類(lèi),通過(guò)這個(gè)類(lèi)我們可以識(shí)別很多的手勢(shì),主要是通過(guò)他的onTouchEvent(event)方法完成了不同手勢(shì)的識(shí)別。雖然他能識(shí)別手勢(shì),但是不同的手勢(shì)要怎么處理,應(yīng)該是提供給程序員實(shí)現(xiàn)的。

一.GestureDetector簡(jiǎn)介

1.組成

GestureDetector類(lèi)用來(lái)識(shí)別觸摸屏的各種手勢(shì),它包含了兩個(gè)接口和一個(gè)內(nèi)部類(lèi):

接口:

OnGestureListener:用來(lái)監(jiān)聽(tīng)手勢(shì)事件(6種)。

OnDoubleTapListener:用來(lái)監(jiān)聽(tīng)雙擊事件。

內(nèi)部類(lèi):

SimpleOnGestureListener:用來(lái)監(jiān)聽(tīng)所有的手勢(shì)。實(shí)際上它實(shí)現(xiàn)了上述兩個(gè)接口,不過(guò)方法體是空的,需要我們自己寫(xiě)。我們可以繼承這個(gè)類(lèi),重寫(xiě)里面的方法進(jìn)行手勢(shì)處理。

2.構(gòu)造

GestureDetector gestureDetector = new GestureDetector(GestureDetector.OnGestureListener listener);

GestureDetector gestureDetector = new GestureDetector(Context context,GestureDetector.OnGestureListener listener);

GestureDetector gestureDetector = new GestureDetector(Context context,GestureDetector.SimpleOnGestureListener listener);

3.方法

(1)onTouchEvent(MotionEvent ev) 分析捕捉到的觸摸事件觸發(fā)相應(yīng)的回調(diào)函數(shù)

(2)setIsLongpressEnabled(boolean isLongpressEnabled) 設(shè)置“長(zhǎng)按”是否可用

(3)setOnDoubleTapListener(GestureDetector.OnDoubleTapListener onDoubleTapListener) 設(shè)置雙擊監(jiān)聽(tīng)器

4.使用

流程:

首先,系統(tǒng)捕捉屏幕的觸摸事件(onTouchListener),這時(shí)還未涉及具體手勢(shì),只是簡(jiǎn)單地捕捉到觸摸。

接著,在onTouch()方法中調(diào)用GestureDetector的onTouchEvent()方法,將捕捉到的MotionEvent交給GestureDetector來(lái)處理

最后,還需要實(shí)現(xiàn)抽象方法。

可根據(jù)需要選擇:

重寫(xiě)OnGestureListener并通過(guò)構(gòu)造函數(shù)傳入gestureDetector

重寫(xiě)OnDoubleTapListener并通過(guò)GestureDetector.setOnDoubleTapListener方法傳入gestureDetector

重寫(xiě)SimpleOnGestureListener并通過(guò)構(gòu)造函數(shù)傳入gestureDetector

實(shí)現(xiàn):

注:不要注重我寫(xiě)的類(lèi)是什么類(lèi),要注重實(shí)現(xiàn)方法自定義view和activity中都可以,根據(jù)需要繼承上面三種listener,傳入構(gòu)造函數(shù)即可;

public class TestDemo{

Context context;

public TestDemo(Context context){

this.context = context;

}

private GestureDetectordetector;

private void initView(){

detector =new GestureDetector(context, new MySimple());

detector =new GestureDetector(context, new MyGesture());

detector =new GestureDetector(context, new MyDoubleTap());

setOnTouchListener((v, event) -> {

// 事件監(jiān)聽(tīng)交給手勢(shì)類(lèi)來(lái)處理

detector.onTouchEvent(event);

return true;

});

}

//與上面二選一

@Override

public boolean onTouchEvent(MotionEvent event) {

return detector.onTouchEvent(event);

}

// 手勢(shì)監(jiān)聽(tīng)器類(lèi)SimpleOnGestureListener

? ? private class MySimple extends GestureDetector.SimpleOnGestureListener {

? ? ? ? @Override

? ? ? ? public boolean onSingleTapUp(MotionEvent e) {//一次單獨(dú)的輕擊抬起操作,也就是輕擊一下屏幕,立刻抬起來(lái),才會(huì)有這個(gè)觸發(fā);如果除了Down以外還有其它操作,那就不再是Single操作了,所以也就不會(huì)觸發(fā)這個(gè)事件

? ? ? ? ? ? return super.onSingleTapUp(e);

? ? ? ? }

? ? ? ? @Override

? ? ? ? public void onLongPress(MotionEvent e) {//長(zhǎng)按事件;

? ? ? ? ? ? super.onLongPress(e);

? ? ? ? }

? ? ? ? @Override

? ? ? ? public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {//在屏幕上拖動(dòng)事件,只要手指移動(dòng)就會(huì)執(zhí)行,無(wú)論是用手拖動(dòng)view,或者是以拋的動(dòng)作滾動(dòng),都會(huì)多次觸發(fā),這個(gè)方法在ACTION_MOVE動(dòng)作發(fā)生時(shí)就會(huì)觸發(fā)他不會(huì)執(zhí)行MotionEvent.ACTION_UP,通常用來(lái)實(shí)現(xiàn)放大縮小和移動(dòng)。

? ? ? ? ? ? return false;

? ? ? ? }

? ? ? ? @Override

? ? ? ? public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {//滑動(dòng)屏幕,用戶(hù)按下觸摸屏、快速移動(dòng)后松開(kāi),由1個(gè)MotionEvent ACTION_DOWN, 多個(gè)ACTION_MOVE, 1個(gè)ACTION_UP觸發(fā);是個(gè)甩的動(dòng)作,這個(gè)甩的動(dòng)作是在一個(gè)MotionEvent.ACTION_UP(手指抬起)發(fā)生時(shí)執(zhí)行,通常用來(lái)實(shí)現(xiàn)翻頁(yè)效果

? ? ? ? ? ? return super.onFling(e1, e2, velocityX, velocityY);

? ? ? ? }

? ? ? ? @Override

? ? ? ? public void onShowPress(MotionEvent e) {//down事件發(fā)生而move或則up還沒(méi)發(fā)生前觸發(fā)該事件;

? ? ? ? ? ? super.onShowPress(e);

? ? ? ? }

? ? ? ? @Override

? ? ? ? public boolean onDown(MotionEvent e) {//down事件用戶(hù)按下屏幕

? ? ? ? ? ? return super.onDown(e);

? ? ? ? }

? ? ? ? @Override

? ? ? ? public boolean onDoubleTap(MotionEvent e) {//雙擊事件

? ? ? ? ? ? return super.onDoubleTap(e);

? ? ? ? }

? ? ? ? @Override

? ? ? ? public boolean onDoubleTapEvent(MotionEvent e) {//雙擊間隔中還發(fā)生其他的動(dòng)作。通知DoubleTap手勢(shì)中的事件,包含down、up和move事件(這里指的是在雙擊之間發(fā)生的事件,例如在同一個(gè)地方雙擊會(huì)產(chǎn)生DoubleTap手勢(shì),而在DoubleTap手勢(shì)里面還會(huì)發(fā)生down和up事件,這兩個(gè)事件由該函數(shù)通知)

? ? ? ? ? ? return super.onDoubleTapEvent(e);

? ? ? ? }

? ? ? ? @Override

? ? ? ? public boolean onSingleTapConfirmed(MotionEvent e) {//單擊事件。用來(lái)判定該次點(diǎn)擊是SingleTap而不是DoubleTap,如果連續(xù)點(diǎn)擊兩次就是DoubleTap手勢(shì),如果只點(diǎn)擊一次,系統(tǒng)等待一段時(shí)間后沒(méi)有收到第二次點(diǎn)擊則判定該次點(diǎn)擊為SingleTap而不是DoubleTap,然后觸發(fā)SingleTapConfirmed事件。

? ? ? ? ? ? return super.onSingleTapConfirmed(e);

? ? ? ? }

? ? }

// 手勢(shì)監(jiān)聽(tīng)器類(lèi)GestureListener

? ? private class MyGesture extends GestureDetector.OnGestureListener{

? ? ? ? @Override

? ? ? ? public boolean onDown(MotionEvent e) {//down事件用戶(hù)按下屏幕

? ? ? ? ? ? return false;

? ? ? ? }

? ? ? ? @Override

? ? ? ? public void onShowPress(MotionEvent e) {//down事件發(fā)生瞬間而move或則up還沒(méi)發(fā)生前觸發(fā)該事件;

? ? ? ? }

? ? ? ? @Override

? ? ? ? public boolean onSingleTapUp(MotionEvent e) {//一次單獨(dú)的輕擊抬起操作,也就是輕擊一下屏幕,立刻抬起來(lái),才會(huì)有這個(gè)觸發(fā);如果除了Down以外還有其它操作,那就不再是Single操作了,所以也就不會(huì)觸發(fā)這個(gè)事件;

? ? ? ? ? ? return super.onSingleTapUp(e);

? ? ? ? }

? ? ? ? @Override

? ? ? ? public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {//在屏幕上拖動(dòng)事件,只要手指移動(dòng)就會(huì)執(zhí)行,無(wú)論是用手拖動(dòng)view,或者是以拋的動(dòng)作滾動(dòng),都會(huì)多次觸發(fā),這個(gè)方法在ACTION_MOVE動(dòng)作發(fā)生時(shí)就會(huì)觸發(fā)他不會(huì)執(zhí)行MotionEvent.ACTION_UP,通常用來(lái)實(shí)現(xiàn)放大縮小和移動(dòng)。

? ? ? ? ? ? return false;

? ? ? ? }

? ? ? ? @Override

? ? ? ? public void onLongPress(MotionEvent e) {//長(zhǎng)按事件,超過(guò)一定時(shí)長(zhǎng)觸發(fā)該事件回調(diào);

? ? ? ? ? ? super.onLongPress(e);

? ? ? ? }

? ? ? ? public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {//滑動(dòng)屏幕,用戶(hù)按下觸摸屏、快速移動(dòng)后松開(kāi),由1個(gè)MotionEvent ACTION_DOWN, 多個(gè)ACTION_MOVE, 1個(gè)ACTION_UP觸發(fā);是個(gè)甩的動(dòng)作,這個(gè)甩的動(dòng)作是在一個(gè)MotionEvent.ACTION_UP(手指抬起)發(fā)生時(shí)執(zhí)行,通常用來(lái)實(shí)現(xiàn)翻頁(yè)效果

? ? ? ? ? ? return super.onFling(e1, e2, velocityX, velocityY);

? ? ? ? }

? ? }

// 手勢(shì)監(jiān)聽(tīng)器類(lèi)SimpleOnGestureListener

? ? private class MyDoubleTap extends GestureDetector.OnDoubleTapListener {

? ? ? ? @Override

? ? ? ? public boolean onDoubleTap(MotionEvent e) {//雙擊事件

? ? ? ? ? ? return super.onDoubleTap(e);

? ? ? ? }

? ? ? ? @Override

? ? ? ? public boolean onDoubleTapEvent(MotionEvent e) {//雙擊間隔中還發(fā)生其他的動(dòng)作。通知DoubleTap手勢(shì)中的事件,包含down、up和move事件(這里指的是在雙擊之間發(fā)生的事件,例如在同一個(gè)地方雙擊會(huì)產(chǎn)生DoubleTap手勢(shì),而在DoubleTap手勢(shì)里面還會(huì)發(fā)生down和up事件,這兩個(gè)事件由該函數(shù)通知)

? ? ? ? ? ? return super.onDoubleTapEvent(e);

? ? ? ? }

? ? ? ? @Override

? ? ? ? public boolean onSingleTapConfirmed(MotionEvent e) {//單擊事件。用來(lái)判定該次點(diǎn)擊是SingleTap而不是DoubleTap,如果連續(xù)點(diǎn)擊兩次就是DoubleTap手勢(shì),如果只點(diǎn)擊一次,系統(tǒng)等待一段時(shí)間后沒(méi)有收到第二次點(diǎn)擊則判定該次點(diǎn)擊為SingleTap而不是DoubleTap,然后觸發(fā)SingleTapConfirmed事件。

? ? ? ? ? ? return super.onSingleTapConfirmed(e);

? ? ? ? }

? ? }

}

關(guān)于onFling()和onScroll()的區(qū)別:

onFling()是甩,這個(gè)甩的動(dòng)作是在一個(gè)MotionEvent.ACTION_UP(手指抬起)發(fā)生時(shí)執(zhí)行,而onScroll(),只要手指移動(dòng)就會(huì)執(zhí)行。他不會(huì)執(zhí)行MotionEvent.ACTION_UP。onFling通常用來(lái)實(shí)現(xiàn)翻頁(yè)效果,而onScroll通常用來(lái)實(shí)現(xiàn)放大縮小和移動(dòng)。

關(guān)于onSingleTapConfirmed和onSingleTapUp的一點(diǎn)區(qū)別: OnGestureListener有這樣的一個(gè)方法onSingleTapUp,和onSingleTapConfirmed容易混淆。二者的區(qū)別是:onSingleTapUp,只要手抬起就會(huì)執(zhí)行,而對(duì)于onSingleTapConfirmed來(lái)說(shuō),如果雙擊的話,則onSingleTapConfirmed不會(huì)執(zhí)行

SimpleOnGestureListener是GestureDetector類(lèi)的一個(gè)內(nèi)部類(lèi),該類(lèi)是static class,也就是說(shuō)它實(shí)際上是一個(gè)外部類(lèi)??梢栽谕獠坷^承這個(gè)類(lèi),重寫(xiě)里面的手勢(shì)處理方法。

1.OnDoubleTapListener是用來(lái)檢測(cè)鼠標(biāo)雙擊事件的

2.SimpleOnGestureListener實(shí)際上實(shí)現(xiàn)了OnGestureListener 和OnDoubleTapListener,所以它可以完成以上提到的所有手勢(shì)識(shí)別(9種)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容