觸摸事件與手勢監聽--Android GestureDetector詳解

目錄

  • 事件監聽的方法
  • GestureDetector類
  • GestureDetector使用方法
  • GesturetDetector.OnGestureListener 接口
  • GesttureDetector.OnDoubleTapListener 接口
  • GesttureDetector.SimpleOnGestureListener 類

事件監聽的方法

在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中處理。

GestureDector類

GestureDector類需要注意以下內容:

  1. OnGestureListener接口
  2. OnDoubleTapListener雙擊接口
  3. SimpleOnGestureListener 類(實現了類內的三個接口)
  4. onTouchEvent()方法
  5. setOnDoubleTapListener()雙擊監聽

    當屏幕上發生特定的觸摸事件,就會去回調GestureDector.OnGestureListener和GestureDetector.OnDoubleTapListener接口中相應的回調函數來監測各樣的手勢和事件,並且通知用戶。但是這些觸發函數都沒有具體的實現,我們必須實現這些接口,並重寫這些方法的具體實現。
    GestureDetector類中已經爲我們定義了一個靜態內部類SimpleOnGestureListener,它實現了OnGestureListener,OnDoubleTapListener,OnContextClickListener接口,定義爲

public static class SimpleOnGestureListener implements OnGestureListener, OnDoubleTapListener,
            OnContextClickListener 

SimpleOnGestureListener類內重寫接口中的所有方法,但是都是空實現,返回的布爾值都是false。主要作用是方便我們繼承這個類有選擇的複寫回調方法,而不是實現接口去重寫所有的方法。
onTouchEvent()方法用來分析傳入的事件,如果匹配的話就去觸發OnGestureListener中相應的回調方法。
如果要監聽雙擊事件必須調用GestureDector.setOnDoubleTapListener()

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日誌,具體功能自己根據業務重寫。

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

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

GesttureDetector.SimpleOnGestureListener 類

結合了OnGestureListener,OnDoubleTapListener和
OnContextClickListener中的所有方法,可以有選擇的去重寫其中的方法,參考前兩節。

發佈了15 篇原創文章 · 獲贊 9 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章