Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android之手勢的識別與處理(雙擊onDoubleTap、滑動onFling、拖動onScroll)

Android之手勢的識別與處理(雙擊onDoubleTap、滑動onFling、拖動onScroll)

編輯:關於Android編程

概述:

一般情況下,我們知道View類有個View.OnTouchListener內部接口,通過重寫他的onTouch(View v, MotionEvent event)方法,我們可以處理一些touch事件,但是這個方法太過簡單,如果需要處理一些復雜的手勢,用這個接口就會很麻煩(因為我們要自己根據用戶觸摸的軌跡去判斷是什麼手勢)。
Android sdk給我們提供了GestureDetector(Gesture:手勢Detector:識別)類,通過這個類我們可以識別很多的手勢,主要是通過他的onTouchEvent(event)方法完成了不同手勢的識別。雖然他能識別手勢,但是不同的手勢要怎麼處理,應該是提供給程序員實現的。
GestureDetector這個類對外提供了兩個接口:OnGestureListener,OnDoubleTapListener,還有一個內部類SimpleOnGestureListener。
GestureDetector.OnDoubleTapListener接口:用來通知DoubleTap事件,類似於鼠標的雙擊事件。
1,onDoubleTap(MotionEvent e):在雙擊的第二下,Touch down時觸發 。
2,onDoubleTapEvent(MotionEvent e):通知DoubleTap手勢中的事件,包含down、up和move事件(這裡指的是在雙擊之間發生的事件,例如在同一個地方雙擊會產生DoubleTap手勢,而在DoubleTap手勢裡面還會發生down和up事件,這兩個事件由該函數通知);雙擊的第二下Touch down和up都會觸發,可用e.getAction()區分。
3,onSingleTapConfirmed(MotionEvent e):用來判定該次點擊是SingleTap而不是DoubleTap,如果連續點擊兩次就是DoubleTap手勢,如果只點擊一次,系統等待一段時間後沒有收到第二次點擊則判定該次點擊為SingleTap而不是DoubleTap,然後觸發SingleTapConfirmed事件。這個方法不同於onSingleTapUp,他是在GestureDetector確信用戶在第一次觸摸屏幕後,沒有緊跟著第二次觸摸屏幕,也就是不是“雙擊”的時候觸發
GestureDetector.OnGestureListener接口:用來通知普通的手勢事件,該接口有如下六個回調函數:
1. onDown(MotionEvent e):down事件;
2. onSingleTapUp(MotionEvent e):一次點擊up事件;在touch down後又沒有滑動
(onScroll),又沒有長按(onLongPress),然後Touchup時觸發。
點擊一下非常快的(不滑動)Touchup:
onDown->onSingleTapUp->onSingleTapConfirmed
點擊一下稍微慢點的(不滑動)Touchup:
onDown->onShowPress->onSingleTapUp->onSingleTapConfirmed
3. onShowPress(MotionEvent e):down事件發生而move或則up還沒發生前觸發該
事件;Touch了還沒有滑動時觸發(與onDown,onLongPress)比較onDown只要Touch down一定立刻觸發。而Touchdown後過一會沒有滑動先觸發onShowPress再是onLongPress。所以Touchdown後一直不滑動
按照onDown->onShowPress->onLongPress這個順序觸發。
4. onLongPress(MotionEvent e):長按事件;Touch了不移動一直Touch down時觸發;
5. onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY):滑動手
勢事件;Touch了滑動一點距離後,在ACTION_UP時才會觸發 ;
參數:e1 第1個ACTION_DOWN MotionEvent 並且只有一個;e2 最後一個ACTION_MOVE MotionEvent ;velocityX X軸上的移動速度,像素/秒 ;velocityY Y軸上的移動速度,像素/秒.觸發條件:X軸的坐標位移大於FLING_MIN_DISTANCE,且移動速度大於FLING_MIN_VELOCITY個像素/秒
6. onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY):在屏幕上
拖動事件。無論是用手拖動view,或者是以拋的動作滾動,都會多次觸發,這個方法在ACTION_MOVE動作發生時就會觸發。

點擊一下非常快的(不滑動)Touchup:
onDown->onSingleTapUp->onSingleTapConfirmed
點擊一下稍微慢點的(不滑動)Touchup:
onDown->onShowPress->onSingleTapUp->onSingleTapConfirmed

Demo

自定義Button控件,實現手勢的監聽和處理:

public class MyButton extends Button {

    private GestureDetector mGesture;
    private OnDoubleClickListener onDoubleClickListener;
    //自定義監聽器接口
    interface OnDoubleClickListener{
        void onDoubleClick(View view);
    }
    //設置雙擊事件監聽器的方法
    public void setOnDoubleClickListener(OnDoubleClickListener onDoubleClickListener){
        this.onDoubleClickListener = onDoubleClickListener;
    };

    public MyButton(Context context) {
        super(context);
    }

    public MyButton(final Context context, AttributeSet attrs) {
        super(context, attrs);
        //
        mGesture = new GestureDetector(context,new GestureDetector.SimpleOnGestureListener(){
            @Override
            public boolean onDoubleTap(MotionEvent e) {
                if(onDoubleClickListener!=null) {
                    onDoubleClickListener.onDoubleClick(MyButton.this);
                }
                Toast.makeText(context,雙擊事件,Toast.LENGTH_SHORT).show();
                return true;
            }

            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                /**
                 * 滑動和拖拽最好不要一起實現,會產生矛盾
                 */
                if(Math.abs(e1.getX()-e2.getX())>50){
                    setTranslationX(e2.getX() - e1.getX());
                    //根據手勢滑動的距離而在水平方向上滑動控件
                    ObjectAnimator.ofFloat(MyButton.this,translationX,getTranslationX(),e2.getX()-e1.getX())
                            .setDuration(500).start();
                    return true;
                }
                return super.onFling(e1, e2, velocityX, velocityY);
            }

            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
                //根據手勢拖拽控件的相位而移動控件
                setTranslationX(getTranslationX()+e2.getX() - e1.getX());
                setTranslationY(getTranslationX()+e2.getY() - e1.getY());
                return super.onScroll(e1, e2, distanceX, distanceY);
            }
        });
    }

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

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        if(event.getAction()==MotionEvent.ACTION_DOWN){

        }
        return super.dispatchTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //touch事件傳給onTouchEvent()
        mGesture.onTouchEvent(event);
        return super.onTouchEvent(event);
    }
}

布局:



    

主活動:

public class MainActivity extends Activity {

    private MyButton myButton;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        myButton = (MyButton) findViewById(R.id.button_doubleTap);
        myButton.setOnDoubleClickListener(new MyButton.OnDoubleClickListener() {
            @Override
            public void onDoubleClick(View view) {
                Log.d(,點擊兩次);
            }
        });
    }

}

結果演示:
雙擊:
這裡寫圖片描述

滑動:<喎?/kf/ware/vc/" target="_blank" class="keylink">vc3Ryb25nPjxiciAvPg0KPGltZyBhbHQ9"這裡寫圖片描述" src="/uploadfile/Collfiles/20150928/2015092808542559.gif" title="\" />

拖拽:
這裡寫圖片描述

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved