Android手勢監聽類GestureDetector的使用

在使用自定義視圖的時候,對觸屏事件的處理是比不可少的,有能力的能夠本身寫代碼處理,這樣更加的靈活。若是不想這麼麻煩,Android提供了一個手勢監聽類GestureDetector,能夠供咱們使用。GestureDetector使用很方便,提供了單擊,雙擊,長按等操做的處理,可是通常的定義界面都比較複雜,還用不少須要注意的地方,在這兒總結一下GestureDetector的使用。android

首先新建一個空白的工程,主界面的layout中只須要添加一個按鈕就行web

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    緩存

  2.     xmlns:tools="http://schemas.android.com/tools"
    app

  3.     android:layout_width="match_parent"
    框架

  4.     android:layout_height="match_parent"
    ide

  5.     android:paddingBottom="@dimen/activity_vertical_margin"
    函數

  6.     android:paddingLeft="@dimen/activity_horizontal_margin"
    測試

  7.     android:paddingRight="@dimen/activity_horizontal_margin"
    this

  8.     android:paddingTop="@dimen/activity_vertical_margin"
    spa

  9.     tools:context=".MainActivity" >


  10.     <Button

  11.         android:id="@+id/btn_textgesture"

  12.         android:layout_width="fill_parent"

  13.         android:layout_height="fill_parent"

  14.         android:text="@string/app_name" />


  15. </RelativeLayout>

複製代碼

因爲要測試的觸屏事件,全部這個按鈕比較大,主界面爲以下效果: 首先介紹一下觸屏事件處理的基本思路。觸屏通常有三個基本事件,down按下,move移動,up離開,經過對這三個基本事件的監聽,判斷用戶執行了何種操做。一個標準的觸屏操做通常都是一系列基本事件的組合,在Android的框架中,經過onTouch()函數能夠獲取基本的觸屏事件,而像onClick這樣的函數,已是一系列基本事件的組合。好比,發生了Down事件,在up事件以前沒有發生move事件,或者move的範圍很小,而且down事件和up事件的間隔很短,這就是一個click或者singelTap事件,對比實體鍵盤按鍵的事件,實體鍵盤是在down事件發生後進行操做,而觸屏事件通常是up事件發生後進行操做。下面是activity的代碼

  1. package com.example.testgesture;


  2. import android.app.Activity;

  3. import android.os.Bundle;

  4. import android.util.Log;

  5. import android.view.GestureDetector;

  6. import android.view.GestureDetector.SimpleOnGestureListener;

  7. import android.view.MotionEvent;

  8. import android.view.View;

  9. import android.view.View.OnTouchListener;

  10. import android.widget.Button;


  11. public class MainActivity extends Activity {


  12.     private Button mButton;

  13.     private GestureDetector mGestureDetector;


  14.     @Override

  15.     protected void onCreate(Bundle savedInstanceState) {

  16.         super.onCreate(savedInstanceState);

  17.         setContentView(R.layout.activity_main);


  18.         mGestureDetector = new GestureDetector(this, new MyOnGestureListener());


  19.         mButton = (Button) findViewById(R.id.btn_textgesture);

  20.         mButton.setOnTouchListener(new OnTouchListener() {


  21.             @Override

  22.             public boolean onTouch(View v, MotionEvent event) {

  23.                 Log.i(getClass().getName(), "onTouch-----" + getActionName(event.getAction()));

  24.                 mGestureDetector.onTouchEvent(event);

  25.                 // 必定要返回true,否則獲取不到完整的事件

  26.                 return true;

  27.             }

  28.         });

  29.     }


  30.     private String getActionName(int action) {

  31.         String name = "";

  32.         switch (action) {

  33.             case MotionEvent.ACTION_DOWN: {

  34.                 name = "ACTION_DOWN";

  35.                 break;

  36.             }

  37.             case MotionEvent.ACTION_MOVE: {

  38.                 name = "ACTION_MOVE";

  39.                 break;

  40.             }

  41.             case MotionEvent.ACTION_UP: {

  42.                 name = "ACTION_UP";

  43.                 break;

  44.             }

  45.             default:

  46.             break;

  47.         }

  48.         return name;

  49.     }


  50.     class MyOnGestureListener extends SimpleOnGestureListener {

  51.         @Override

  52.         public boolean onSingleTapUp(MotionEvent e) {

  53.             Log.i(getClass().getName(), "onSingleTapUp-----" + getActionName(e.getAction()));

  54.             return false;

  55.         }


  56.         @Override

  57.         public void onLongPress(MotionEvent e) {

  58.             Log.i(getClass().getName(), "onLongPress-----" + getActionName(e.getAction()));

  59.         }


  60.         @Override

  61.         public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {

  62.             Log.i(getClass().getName(),

  63.                     "onScroll-----" + getActionName(e2.getAction()) + ",(" + e1.getX() + "," + e1.getY() + ") ,("

  64.                             + e2.getX() + "," + e2.getY() + ")");

  65.             return false;

  66.         }


  67.         @Override

  68.         public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {

  69.             Log.i(getClass().getName(),

  70.                     "onFling-----" + getActionName(e2.getAction()) + ",(" + e1.getX() + "," + e1.getY() + ") ,("

  71.                             + e2.getX() + "," + e2.getY() + ")");

  72.             return false;

  73.         }


  74.         @Override

  75.         public void onShowPress(MotionEvent e) {

  76.             Log.i(getClass().getName(), "onShowPress-----" + getActionName(e.getAction()));

  77.         }


  78.         @Override

  79.         public boolean onDown(MotionEvent e) {

  80.             Log.i(getClass().getName(), "onDown-----" + getActionName(e.getAction()));

  81.             return false;

  82.         }


  83.         @Override

  84.         public boolean onDoubleTap(MotionEvent e) {

  85.             Log.i(getClass().getName(), "onDoubleTap-----" + getActionName(e.getAction()));

  86.             return false;

  87.         }


  88.         @Override

  89.         public boolean onDoubleTapEvent(MotionEvent e) {

  90.             Log.i(getClass().getName(), "onDoubleTapEvent-----" + getActionName(e.getAction()));

  91.             return false;

  92.         }


  93.         @Override

  94.         public boolean onSingleTapConfirmed(MotionEvent e) {

  95.             Log.i(getClass().getName(), "onSingleTapConfirmed-----" + getActionName(e.getAction()));

  96.             return false;

  97.         }

  98.     }

  99. }

複製代碼

首先是聲明一個GestureDetector,而後重寫Button的onTouch函數,將觸屏事件交給GestureDetector處理。 首先作一個對按鈕作一個單擊   onSingleTapUp被調用,說明發生了單擊事件,onSingleTapConfirmed被調用,說明確認發生了一個單擊事件,不是雙擊的事件。須要注意的是onSingleTapUp已是一click事件,onSingleTapUp觸發的時候是 ACTION_UP事件。onSingleTapConfirmed是在用戶手指 離開屏幕後觸發,全部up並非全部觸屏事件的結束。 作一個雙擊的操做  首先發生了一個onSingleTapUp,說明完成了一次單擊事件,而後發生了onDoubleTap,至此,一次雙擊事件已經完成。咱們能夠看到,onDoubleTap發生的時候是 ACTION_DOWN事件,也就是說雙擊事件是第二次按下屏幕的時候觸發,而不是第二次離開屏幕的時候觸發,在onDoubleTap發生以後,就能夠在onDoubleTapEvent中監聽到雙擊事件發生後從按下到彈起的全部觸屏事件。onDoubleTap發生後不會觸發onSingleTapUp和onSingleTapConfirmed。 作一個長按的操做  onLongPress實在 ACTION_DOWN時發生,onLongPress發生後在up以前不會用其餘事件觸發,能夠在 onShowPress處理狀態的改變,好比按鈕的按下狀態。 作一個滑動操做 onScroll事件是拖動,onFling是拋。結合log來了解一下。首先是ACTION_DOWN,以後屢次ACTION_MOVE,移動超過必定距離,觸發了onScroll,若是onScroll被觸發, 在up以前是不會有長按,單擊,雙擊等事件的。看一下onScroll的參數
  1. public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)

複製代碼

e1爲第一次按下的事件,和onDown事件裏面的同樣,e2爲當前的事件,distanceX爲本次onScroll移動的X軸距離,distanceY爲移動的Y軸距離,移動的距離是相對於上一次onScroll事件的移動距離,而不是當前點和按下點的距離。此次滑動最後觸發了onFling事件,可是onFling事件的觸發不是必定的,onFling是在ACTION_UP觸發,平時列表在離開屏幕是繼續滾動,就是經過這種方式觸發。
  1. public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)

複製代碼

onFling的前兩個參數和onScroll相同,e2爲用戶拖動完離開屏幕時的點。veloctiyX,velocitY爲離開屏幕時的初始速度,以這兩個速度爲初始速度作勻減速運動,就是如今拖動列表和拖動圖片的各類緩存滾動的效果。 函數的返回值除了onLongPress,這些函數都是有返回值的,
  1. mButton.setOnTouchListener(new OnTouchListener() {


  2.             @Override

  3.             public boolean onTouch(View v, MotionEvent event) {

  4.                 Log.i(getClass().getName(), "onTouch-----" + getActionName(event.getAction()));

  5.                 mGestureDetector.onTouchEvent(event);

  6.                 // 必定要返回true,否則獲取不到完整的事件

  7.                 return true;

  8.             }

  9.         });

複製代碼

這些返回值會經過 mGestureDetector.onTouchEvent(event); 傳遞給onTouch。
最後總結一下GestureDetector結合SimpleOnGestureListener能夠很方便的獲取到單擊,雙擊,長按等事件,可是對這些事件的處理不是簡單的在對應的函數裏作一些操做就能夠的,複雜的自定義視圖仍是要在onTouch裏面進行判斷個個控件的焦點狀態,並且GestureDetector也不是萬能的,你若是要處理長按以後的移動,就要費一番功夫了,覺得GestureDetector在長按發生後是不會在有onScroll的,你只能經過onTouch裏面的ACTION_MOVE處理。
相關文章
相關標籤/搜索