app我們常用的手勢有很多的地方罩润,比如右滑關(guān)閉界面等荠察。手勢控制分為觸發(fā)動(dòng)作(Touch Mechanics蚤霞,用戶手指在屏幕上如何動(dòng)作)和觸發(fā)行為(Touch Activities挑豌,界面上特定動(dòng)作在特定情境下引發(fā)的結(jié)果)安券。這是因?yàn)橥瑯拥挠|發(fā)動(dòng)作(如單次觸擊)在不同情境下可能會(huì)帶來不同的結(jié)果(如輕觸,取消氓英,開啟/關(guān)閉指示)侯勉,同樣單次觸發(fā)行為(如放大)可能是由多種觸發(fā)動(dòng)作(如捏放,雙次觸擊铝阐,雙次觸擊拖拽等)實(shí)現(xiàn)址貌。
? ? 一般情況下,我們知道View類有個(gè)View.OnTouchListener內(nèi)部接口,通過重寫他的onTouch(View v, MotionEvent event)方法练对,我們可以處理一些touch事件余舶,但是這個(gè)方法太過簡單,如果需要處理一些復(fù)雜的手勢锹淌,用這個(gè)接口就會(huì)很麻煩(因?yàn)槲覀円约焊鶕?jù)用戶觸摸的軌跡去判斷是什么手勢)。
? ? Android sdk給我們提供了GestureDetector類赠制,通過這個(gè)類我們可以識別很多的手勢赂摆,主要是通過他的onTouchEvent(event)方法完成了不同手勢的識別。雖然他能識別手勢钟些,但是不同的手勢要怎么處理烟号,應(yīng)該是提供給程序員實(shí)現(xiàn)的。
一.GestureDetector簡介
1.組成
GestureDetector類用來識別觸摸屏的各種手勢政恍,它包含了兩個(gè)接口和一個(gè)內(nèi)部類:
接口:
OnGestureListener:用來監(jiān)聽手勢事件(6種)汪拥。
OnDoubleTapListener:用來監(jiān)聽雙擊事件。
內(nèi)部類:
SimpleOnGestureListener:用來監(jiān)聽所有的手勢篙耗。實(shí)際上它實(shí)現(xiàn)了上述兩個(gè)接口迫筑,不過方法體是空的,需要我們自己寫宗弯。我們可以繼承這個(gè)類脯燃,重寫里面的方法進(jìn)行手勢處理。
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è)置“長按”是否可用
(3)setOnDoubleTapListener(GestureDetector.OnDoubleTapListener onDoubleTapListener) 設(shè)置雙擊監(jiān)聽器
4.使用
流程:
首先蒙保,系統(tǒng)捕捉屏幕的觸摸事件(onTouchListener),這時(shí)還未涉及具體手勢辕棚,只是簡單地捕捉到觸摸。
接著邓厕,在onTouch()方法中調(diào)用GestureDetector的onTouchEvent()方法逝嚎,將捕捉到的MotionEvent交給GestureDetector來處理
最后,還需要實(shí)現(xiàn)抽象方法详恼。
可根據(jù)需要選擇:
重寫OnGestureListener并通過構(gòu)造函數(shù)傳入gestureDetector
重寫OnDoubleTapListener并通過GestureDetector.setOnDoubleTapListener方法傳入gestureDetector
重寫SimpleOnGestureListener并通過構(gòu)造函數(shù)傳入gestureDetector
實(shí)現(xiàn):
注:不要注重我寫的類是什么類补君,要注重實(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)聽交給手勢類來處理
detector.onTouchEvent(event);
return true;
});
}
//與上面二選一
@Override
public boolean onTouchEvent(MotionEvent event) {
return detector.onTouchEvent(event);
}
// 手勢監(jiān)聽器類SimpleOnGestureListener
? ? private class MySimple extends GestureDetector.SimpleOnGestureListener {
? ? ? ? @Override
? ? ? ? public boolean onSingleTapUp(MotionEvent e) {//一次單獨(dú)的輕擊抬起操作,也就是輕擊一下屏幕,立刻抬起來硅堆,才會(huì)有這個(gè)觸發(fā)屿储;如果除了Down以外還有其它操作,那就不再是Single操作了,所以也就不會(huì)觸發(fā)這個(gè)事件
? ? ? ? ? ? return super.onSingleTapUp(e);
? ? ? ? }
? ? ? ? @Override
? ? ? ? public void onLongPress(MotionEvent e) {//長按事件;
? ? ? ? ? ? super.onLongPress(e);
? ? ? ? }
? ? ? ? @Override
? ? ? ? public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {//在屏幕上拖動(dòng)事件,只要手指移動(dòng)就會(huì)執(zhí)行渐逃,無論是用手拖動(dòng)view够掠,或者是以拋的動(dòng)作滾動(dòng),都會(huì)多次觸發(fā),這個(gè)方法在ACTION_MOVE動(dòng)作發(fā)生時(shí)就會(huì)觸發(fā)他不會(huì)執(zhí)行MotionEvent.ACTION_UP,通常用來實(shí)現(xiàn)放大縮小和移動(dòng)茄菊。
? ? ? ? ? ? return false;
? ? ? ? }
? ? ? ? @Override
? ? ? ? public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {//滑動(dòng)屏幕疯潭,用戶按下觸摸屏赊堪、快速移動(dòng)后松開,由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í)行,通常用來實(shí)現(xiàn)翻頁效果
? ? ? ? ? ? return super.onFling(e1, e2, velocityX, velocityY);
? ? ? ? }
? ? ? ? @Override
? ? ? ? public void onShowPress(MotionEvent e) {//down事件發(fā)生而move或則up還沒發(fā)生前觸發(fā)該事件哭廉;
? ? ? ? ? ? super.onShowPress(e);
? ? ? ? }
? ? ? ? @Override
? ? ? ? public boolean onDown(MotionEvent e) {//down事件用戶按下屏幕
? ? ? ? ? ? return super.onDown(e);
? ? ? ? }
? ? ? ? @Override
? ? ? ? public boolean onDoubleTap(MotionEvent e) {//雙擊事件
? ? ? ? ? ? return super.onDoubleTap(e);
? ? ? ? }
? ? ? ? @Override
? ? ? ? public boolean onDoubleTapEvent(MotionEvent e) {//雙擊間隔中還發(fā)生其他的動(dòng)作。通知DoubleTap手勢中的事件相叁,包含down遵绰、up和move事件(這里指的是在雙擊之間發(fā)生的事件,例如在同一個(gè)地方雙擊會(huì)產(chǎn)生DoubleTap手勢增淹,而在DoubleTap手勢里面還會(huì)發(fā)生down和up事件椿访,這兩個(gè)事件由該函數(shù)通知)
? ? ? ? ? ? return super.onDoubleTapEvent(e);
? ? ? ? }
? ? ? ? @Override
? ? ? ? public boolean onSingleTapConfirmed(MotionEvent e) {//單擊事件。用來判定該次點(diǎn)擊是SingleTap而不是DoubleTap虑润,如果連續(xù)點(diǎn)擊兩次就是DoubleTap手勢成玫,如果只點(diǎn)擊一次,系統(tǒng)等待一段時(shí)間后沒有收到第二次點(diǎn)擊則判定該次點(diǎn)擊為SingleTap而不是DoubleTap拳喻,然后觸發(fā)SingleTapConfirmed事件哭当。
? ? ? ? ? ? return super.onSingleTapConfirmed(e);
? ? ? ? }
? ? }
// 手勢監(jiān)聽器類GestureListener
? ? private class MyGesture extends GestureDetector.OnGestureListener{
? ? ? ? @Override
? ? ? ? public boolean onDown(MotionEvent e) {//down事件用戶按下屏幕
? ? ? ? ? ? return false;
? ? ? ? }
? ? ? ? @Override
? ? ? ? public void onShowPress(MotionEvent e) {//down事件發(fā)生瞬間而move或則up還沒發(fā)生前觸發(fā)該事件;
? ? ? ? }
? ? ? ? @Override
? ? ? ? public boolean onSingleTapUp(MotionEvent e) {//一次單獨(dú)的輕擊抬起操作,也就是輕擊一下屏幕冗澈,立刻抬起來荣病,才會(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í)行个盆,無論是用手拖動(dòng)view,或者是以拋的動(dòng)作滾動(dòng)朵栖,都會(huì)多次觸發(fā),這個(gè)方法在ACTION_MOVE動(dòng)作發(fā)生時(shí)就會(huì)觸發(fā)他不會(huì)執(zhí)行MotionEvent.ACTION_UP,通常用來實(shí)現(xiàn)放大縮小和移動(dòng)颊亮。
? ? ? ? ? ? return false;
? ? ? ? }
? ? ? ? @Override
? ? ? ? public void onLongPress(MotionEvent e) {//長按事件,超過一定時(shí)長觸發(fā)該事件回調(diào)陨溅;
? ? ? ? ? ? super.onLongPress(e);
? ? ? ? }
? ? ? ? public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {//滑動(dòng)屏幕终惑,用戶按下觸摸屏、快速移動(dòng)后松開门扇,由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í)行,通常用來實(shí)現(xiàn)翻頁效果
? ? ? ? ? ? return super.onFling(e1, e2, velocityX, velocityY);
? ? ? ? }
? ? }
// 手勢監(jiān)聽器類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手勢中的事件臼寄,包含down霸奕、up和move事件(這里指的是在雙擊之間發(fā)生的事件,例如在同一個(gè)地方雙擊會(huì)產(chǎn)生DoubleTap手勢吉拳,而在DoubleTap手勢里面還會(huì)發(fā)生down和up事件质帅,這兩個(gè)事件由該函數(shù)通知)
? ? ? ? ? ? return super.onDoubleTapEvent(e);
? ? ? ? }
? ? ? ? @Override
? ? ? ? public boolean onSingleTapConfirmed(MotionEvent e) {//單擊事件。用來判定該次點(diǎn)擊是SingleTap而不是DoubleTap,如果連續(xù)點(diǎn)擊兩次就是DoubleTap手勢煤惩,如果只點(diǎn)擊一次嫉嘀,系統(tǒng)等待一段時(shí)間后沒有收到第二次點(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通常用來實(shí)現(xiàn)翻頁效果不狮,而onScroll通常用來實(shí)現(xiàn)放大縮小和移動(dòng)。
關(guān)于onSingleTapConfirmed和onSingleTapUp的一點(diǎn)區(qū)別: OnGestureListener有這樣的一個(gè)方法onSingleTapUp在旱,和onSingleTapConfirmed容易混淆摇零。二者的區(qū)別是:onSingleTapUp,只要手抬起就會(huì)執(zhí)行桶蝎,而對于onSingleTapConfirmed來說驻仅,如果雙擊的話,則onSingleTapConfirmed不會(huì)執(zhí)行
SimpleOnGestureListener是GestureDetector類的一個(gè)內(nèi)部類登渣,該類是static class噪服,也就是說它實(shí)際上是一個(gè)外部類∈ぜ耄可以在外部繼承這個(gè)類粘优,重寫里面的手勢處理方法。
1.OnDoubleTapListener是用來檢測鼠標(biāo)雙擊事件的
2.SimpleOnGestureListener實(shí)際上實(shí)現(xiàn)了OnGestureListener 和OnDoubleTapListener呻顽,所以它可以完成以上提到的所有手勢識別(9種)