徹底理解Android手勢開發(fā)GestureDecetor之使用篇

人生和游戲一樣,需要不斷的打怪升級,等到了一定的等級,也就打開了新的天地!

1、簡介

Android手勢常見的有單擊、雙擊、長按、滑動、快速滑動、上滑、下滑、左滑、右滑等等。
我們一般重寫View的onTouchEvent(MotionEvent event)然后做一些處理。基本的代碼格式:

 @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getActionMasked();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                //邏輯處理
                break;
            case MotionEvent.ACTION_MOVE:
                //邏輯處理
                break;
            case MotionEvent.ACTION_UP:
                //邏輯處理
                break;
            default:
                break;
        }
        return true;
    }

這一部分代碼的處理基本是一致的。于是強大的谷歌提供了GestureDetector類來簡化我們對手勢的處理。
下面我們來看看手勢開發(fā)的API

2、API介紹

手勢開發(fā)涉及的API

  • GestureDetector(手勢管理器)
  • GestureDetector.OnGestureListener(接口,提供一些回調(diào)的手勢方法)
  • GestureDetector.OnDoubleTapListener(接口,提供一些回調(diào)的手勢方法)
  • GestureDetector.OnContextClickListener(接口,提供一些回調(diào)的手勢方法)
  • GestureDetector.SimpleOnGestureListener(空實現(xiàn)了上面的三個手勢接口,供開發(fā)者重寫指定的手勢方法)

2.1、GestureDetector API

手勢追蹤管理器

  • 構(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) 
構(gòu)造方法最終都走到了四個參數(shù)的構(gòu)造方法。
參數(shù):context //上下文,基本都要傳入的參數(shù)
參數(shù):OnGestureListener //傳入一個手勢回調(diào)接口
參數(shù):handler //可以改變內(nèi)部handler的Looper,下一篇原理篇講解
參數(shù):unused //這個參數(shù)目前源碼中沒有用到
  • 對外方法
isLongpressEnabled() //是否支持長按手勢
setIsLongpressEnabled(boolean isLongpressEnabled)//設(shè)置是否允許長按操作
setOnDoubleTapListener(OnDoubleTapListener onDoubleTapListener)//配置這個接口中支持的手勢,下面可以看這個接口支持的手勢方法
setContextClickListener(OnContextClickListener onContextClickListener)//配置這個接口中支持的手勢,下面可以看這個接口支持的手勢方法
onTouchEvent(MotionEvent ev)//核心方法,處理各種手勢的邏輯在這個里面

2.2、GestureDetector.OnGestureListener

boolean onDown(MotionEvent e)// 用戶按下觸發(fā),ACTION_DOWN事件,一次手勢過程中觸發(fā)一次
void onShowPress(MotionEvent e)//用戶按下但是沒有發(fā)生move和up,給用戶一個可視化的反饋方法,一次手勢過程中觸發(fā)一次
onLongPress(MotionEvent e)//長按事件
onSingleTapUp(MotionEvent e)//單擊事件,這個事件發(fā)生了,可能會發(fā)生雙擊事件
onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) //快速滑動事件
參數(shù):e1:快速滑動第一個DOWN事件 e2:觸發(fā)快速滑動的move時間 velocityX:快速滑動事件x方向的速度,單位是px/s,就是每秒劃過了多少的像素 velocityY:y方向的速度和x含義一致。
boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)//滑動事件,滑動過程會頻繁調(diào)用
參數(shù):e1:開始滑動第一個DOWN事件 e2:當(dāng)前的滑動事件 distanceX:前后兩次滑動事件x方向的變化值 distanceY:前后兩次滑動事件y方向的變化值

2.3、GestureDetector.OnDoubleTapListener

boolean onSingleTapConfirmed(MotionEvent e)//嚴(yán)格的單擊事件,這個事件發(fā)生了就不可能會發(fā)生雙擊事件
boolean onDoubleTap(MotionEvent e)//雙擊事件
boolean onDoubleTapEvent(MotionEvent e)//發(fā)生了雙擊事件,在雙擊期間ACTION_DOWN、ACTION_MOVE、ACTION_UP都會觸發(fā)此回調(diào)

2.4、GestureDetector.SimpleOnGestureListener

對上面三個接口進(jìn)行了空實現(xiàn),手勢監(jiān)聽推薦使用這個實現(xiàn)類,這樣我們?nèi)ブ貙懳覀冃枰氖謩莘椒?,就不需要每一個手勢方法都重寫了

3、使用

步驟:
1、構(gòu)建GestureDetector
2、接管View的onTouchEvent事件處理

示例:

public class MyTestView extends AppCompatImageView {

    private static final String TAG = "MyTestView";
    private GestureDetector gestureDetector;

    public MyTestView(Context context) {
        super(context);
        init();
    }

    public MyTestView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MyTestView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        //1、構(gòu)建GestureDetector對象,傳入需要回調(diào)的手勢接口,這里我們傳入手勢接口實現(xiàn)類SimpleOnGestureListener
        gestureDetector = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() {

            @Override
            public boolean onDown(MotionEvent e) {
                Log.d(TAG, "onDown()");
                //此處必須返回true,否則就只能觸發(fā)這個事件和onLongPress()事件了
                //其他的事件都不會觸發(fā)了,這個和android的事件分發(fā)機制有關(guān),后面會寫一篇關(guān)于事件分發(fā)。
                return true;
            }

            @Override
            public void onLongPress(MotionEvent e) {
                super.onLongPress(e);
                Log.d(TAG, "onLongPress()");
            }

            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                Log.d(TAG, "onSingleTapUp()");
                return super.onSingleTapUp(e);
            }

            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
                Log.d(TAG, "onScroll() distanceX:" + distanceX + ",distanceY:" + distanceY);
                ViewGroup viewGroup = (ViewGroup) getParent();
                viewGroup.scrollBy((int) distanceX, (int) distanceY);
                return true;
            }

            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                Log.d(TAG, "onFling()");
                return super.onFling(e1, e2, velocityX, velocityY);
            }

        });
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //2、調(diào)用gestureDetector.onTouchEvent(event)來接管view的onTouchEvent
        return gestureDetector.onTouchEvent(event);
    }
}

4、手勢開發(fā)注意點

  • 手勢方法中凡是有返回值的方法,這些方法的結(jié)果都會返回到view的onTouchEvent方法中,有些方法會影響view的事件分發(fā)。
  • onDown方法要返回true,否則就只能觸發(fā)onDown和onLongPress事件了,其他的都觸發(fā)不了了,原因就是影響了事件分發(fā)過程。
  • onSingleTapUp和onSingleTapConfirmed的區(qū)別:
    都理解是單擊事件,onSingleTapUp事件發(fā)生了,后面還是可能會觸發(fā)onDoubleTap雙擊事件;而onSingleTapConfirmed發(fā)生就是嚴(yán)格的單擊事件后面不會發(fā)生onDoubleTap了。所以對于嚴(yán)格的單擊事件應(yīng)該重寫onSingleTapConfirmed方法
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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