理解Android的手勢識別

     對於觸摸屏,其原生的消息無非按下、擡起、移動這幾種,咱們只須要簡單重載onTouch或者設置觸摸偵聽器setOnTouchListener便可進行處理。不過,爲了提升咱們的APP的用戶體驗,有時候咱們須要識別用戶的手勢,Android給咱們提供的手勢識別工具GestureDetector就能夠幫上大忙了。java

基礎android

GestureDetector的工做原理是,當咱們接收到用戶觸摸消息時,將這個消息交給GestureDetector去加工,咱們經過設置偵聽器得到GestureDetector處理後的手勢。app

 GestureDetector提供了兩個偵聽器接口,OnGestureListener處理單擊類消息,OnDoubleTapListener處理雙擊類消息。ide

OnGestureListener的接口有這幾個: 工具

// 單擊,觸摸屏按下時馬上觸發 測試

abstract boolean onDown(MotionEvent e);

// 擡起,手指離開觸摸屏時觸發(長按、滾動、滑動時,不會觸發這個手勢) this

abstract boolean onSingleTapUp(MotionEvent e);

// 短按,觸摸屏按下後片刻後擡起,會觸發這個手勢,若是迅速擡起則不會 .net

abstract void onShowPress(MotionEvent e);

// 長按,觸摸屏按下後既不擡起也不移動,過一段時間後觸發 code

abstract void onLongPress(MotionEvent e);

// 滾動,觸摸屏按下後移動 對象

abstract boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY);

// 滑動,觸摸屏按下後快速移動並擡起,會先觸發滾動手勢,跟着觸發一個滑動手勢 

abstract boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY);

OnDoubleTapListener的接口有這幾個:

// 雙擊,手指在觸摸屏上迅速點擊第二下時觸發 

abstract boolean onDoubleTap(MotionEvent e);

// 雙擊的按下跟擡起各觸發一次 

abstract boolean onDoubleTapEvent(MotionEvent e);

// 單擊確認,即很快的按下並擡起,但並不連續點擊第二下 

abstract boolean onSingleTapConfirmed(MotionEvent e);

    有時候咱們並不須要處理上面全部手勢,方便起見,Android提供了另一個類SimpleOnGestureListener實現瞭如上接口,咱們只須要繼承SimpleOnGestureListener而後重載感興趣的手勢便可。

應用

STEP 1: 建立手勢偵聽對象

package noodies.blog.csdn.net; 

import android.content.Context; 

import android.view.MotionEvent; 

import android.view.GestureDetector.SimpleOnGestureListener; 

import android.widget.Toast; 

public class MyGestureListener extends SimpleOnGestureListener { 

    private Context mContext; 

    MyGestureListener(Context context) { 

        mContext = context; 

    } 

     

    @Override 

    public boolean onDown(MotionEvent e) { 

        Toast.makeText(mContext, "DOWN " + e.getAction(), Toast.LENGTH_SHORT).show(); 

        return false; 

    } 

 

    @Override 

    public void onShowPress(MotionEvent e) { 

        Toast.makeText(mContext, "SHOW " + e.getAction(), Toast.LENGTH_SHORT).show();            

    } 

 

    @Override 

    public boolean onSingleTapUp(MotionEvent e) { 

        Toast.makeText(mContext, "SINGLE UP " + e.getAction(), Toast.LENGTH_SHORT).show(); 

        return false; 

    } 

 

    @Override 

    public boolean onScroll(MotionEvent e1, MotionEvent e2, 

            float distanceX, float distanceY) { 

        Toast.makeText(mContext, "SCROLL " + e2.getAction(), Toast.LENGTH_SHORT).show(); 

        return false; 

    } 

 

    @Override 

    public void onLongPress(MotionEvent e) { 

        Toast.makeText(mContext, "LONG " + e.getAction(), Toast.LENGTH_SHORT).show(); 

    } 

 

    @Override 

    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, 

            float velocityY) { 

        Toast.makeText(mContext, "FLING " + e2.getAction(), Toast.LENGTH_SHORT).show(); 

        return false; 

    } 

 

    @Override 

    public boolean onDoubleTap(MotionEvent e) { 

        Toast.makeText(mContext, "DOUBLE " + e.getAction(), Toast.LENGTH_SHORT).show(); 

        return false; 

    } 

 

    @Override 

    public boolean onDoubleTapEvent(MotionEvent e) { 

        Toast.makeText(mContext, "DOUBLE EVENT " + e.getAction(), Toast.LENGTH_SHORT).show(); 

        return false; 

    } 

 

    @Override 

    public boolean onSingleTapConfirmed(MotionEvent e) { 

        Toast.makeText(mContext, "SINGLE CONF " + e.getAction(), Toast.LENGTH_SHORT).show(); 

        return false; 

    } 

}

 

STEP 2: 設置手勢識別

 咱們能夠在Activity裏設置手勢識別:

package noodies.blog.csdn.net; 

 import android.app.Activity; 

import android.os.Bundle; 

import android.view.GestureDetector; 

import android.view.MotionEvent; 

public class GestureTestActivity extends Activity { 

    private GestureDetector mGestureDetector; 

    @Override 

    public void onCreate(Bundle savedInstanceState) { 

        super.onCreate(savedInstanceState); 

        setContentView(R.layout.main); 

        mGestureDetector = new GestureDetector(this, new MyGestureListener(this)); 

    } 

 

    @Override 

    public boolean onTouchEvent(MotionEvent event) { 

        return mGestureDetector.onTouchEvent(event); 

    } 

}

 

 也能夠在自定義的View裏面設置手勢識別:

package noodies.blog.csdn.net; 

import android.content.Context; 
import android.util.AttributeSet; 
import android.view.GestureDetector; 
import android.view.MotionEvent; 
import android.view.View; 

 
public class MyView extends View { 

    private GestureDetector mGestureDetector; 

    public MyView(Context context, AttributeSet attrs) { 
        super(context, attrs); 
        mGestureDetector = new GestureDetector(context, new MyGestureListener(context)); 
        setLongClickable(true); 

        this.setOnTouchListener(new OnTouchListener() { 
            public boolean onTouch(View v, MotionEvent event) { 
                return mGestureDetector.onTouchEvent(event); 

            } 
        }); 

    } 

}

陷阱

對於自定義View,使用手勢識別有兩處陷阱可能會浪費你的很多時間。

1:View必須設置longClickable爲true,不然手勢識別沒法正確工做,只會返回Down, Show, Long三種手勢

2:必須在View的onTouchListener中調用手勢識別,而不能像Activity同樣重載onTouchEvent,不然一樣手勢識別沒法正確工做

測試結果

下面是各類操做返回的手勢序列,數值0表示觸摸屏按下,1表示擡起

單擊:down 0, single up 1, single conf 0 

短按:down 0, show 0, single up 1 

長按:down 0, show 0, long 0 

雙擊:down 0, single up 1, double 0, double event 0, down 0, double event 1 

滾動:down 0, (show 0), scrool 2... 

滑動:down 0, (show 0), scrool 2..., fling 1   

相關文章
相關標籤/搜索