Android 手勢識別應用:手把手教你學會 GestureDetector(含實例講解)

前言

  • 手勢識別在Android開發的應用非常常見
  • 今天carson將詳細給大家講解Android手勢識別類:GestureDetector類的使用。(含實例講解)

目錄


簡介

下面,我將結合實例,詳細介紹GestureDetector的使用接口 & 使用類。


接口1:OnGestureListener

1. 作用

檢測用戶在屏幕的以下操作:按下瞬間、按壓、長按、輕擊、快速滑屏、拖動

2. 使用步驟

// 步驟1:創建手勢檢測器實例 & 傳入OnGestureListener接口(需要複寫對應方法)
// 構造函數有3個,常用的是第二個
// 1. GestureDetector gestureDetector=new GestureDetector(GestureDetector.OnGestureListener listener);
// 2. GestureDetector gestureDetector=new GestureDetector(Context context,GestureDetector.OnGestureListener listener);
// 3. GestureDetector gestureDetector=new GestureDetector(Context context,GestureDetector.SimpleOnGestureListener listener);
    GestureDetector mGestureDetector = new GestureDetector(this, new GestureDetector.OnGestureListener() {

        // 1. 用戶輕觸觸摸屏
        public boolean onDown(MotionEvent e) {
            Log.i("MyGesture", "onDown");
            return false;
        }

        // 2. 用戶輕觸觸摸屏,尚未鬆開或拖動
        // 與onDown()的區別:無鬆開 / 拖動
        // 即:當用戶點擊的時,onDown()就會執行,在按下的瞬間沒有鬆開 / 拖動時onShowPress就會執行
        public void onShowPress(MotionEvent e) {
            Log.i("MyGesture", "onShowPress");
        }

        // 3. 用戶長按觸摸屏
        public void onLongPress(MotionEvent e) {
            Log.i("MyGesture", "onLongPress");
        }

        // 4. 用戶輕擊屏幕後擡起
        public boolean onSingleTapUp(MotionEvent e) {
            Log.i("MyGesture", "onSingleTapUp");
            return true;
        }

        // 5. 用戶按下觸摸屏 & 拖動
        public boolean onScroll(MotionEvent e1, MotionEvent e2,
                                float distanceX, float distanceY) {
            Log.i("MyGesture", "onScroll:");
            return true;
        }

        // 6. 用戶按下觸摸屏、快速移動後鬆開
        // 參數:
        // e1:第1個ACTION_DOWN MotionEvent
        // e2:最後一個ACTION_MOVE MotionEvent
        // velocityX:X軸上的移動速度,像素/秒
        // velocityY:Y軸上的移動速度,像素/秒
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                               float velocityY) {
            Log.i("MyGesture", "onFling");
            return true;
        }

    });

// 步驟2-1:讓某個View檢測手勢 - 重寫View的onTouch函數,將View的觸屏事件交給GestureDetector處理,從而對用戶手勢作出響應
    View.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            mGestureDetector.onTouchEvent(event);
            return true; // 注:返回true才能完整接收觸摸事件
        }
    });

// 步驟2-2:讓某個Activity檢測手勢:重寫Activity的dispatchTouchEvent函數,將觸屏事件交給GestureDetector處理,從而對用戶手勢作出響應
  @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        mGestureDetector.onTouchEvent(ev); // 讓GestureDetector響應觸碰事件
        super.dispatchTouchEvent(ev); // 讓Activity響應觸碰事件
        return false;
    }

3. 實例說明

現在對一個TextView進行手勢檢測
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    >

    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="600dp"
        android:text="carson_ho Test"
        android:textAppearance="?android:attr/textAppearanceLarge" />

</LinearLayout>

MainActivity.java

public class MainActivity extends AppCompatActivity {

    TextView mTextView;
    GestureDetector mGestureDetector;

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

        // 步驟1:創建手勢檢測器實例 & 傳入OnGestureListener接口(需要複寫對應方法)
        mGestureDetector = new GestureDetector(this, new GestureDetector.OnGestureListener() {

            // 1. 用戶輕觸觸摸屏
            public boolean onDown(MotionEvent e) {
                Log.i("MyGesture", "onDown");
                return false;
            }

            // 2. 用戶輕觸觸摸屏,尚未鬆開或拖動
            // 與onDown()的區別:無鬆開 / 拖動
            // 即:當用戶點擊的時,onDown()就會執行,在按下的瞬間沒有鬆開 / 拖動時onShowPress就會執行
            public void onShowPress(MotionEvent e) {
                Log.i("MyGesture", "onShowPress");
            }

            // 3. 用戶長按觸摸屏
            public void onLongPress(MotionEvent e) {
                Log.i("MyGesture", "onLongPress");
            }

            // 4. 用戶輕擊屏幕後擡起
            public boolean onSingleTapUp(MotionEvent e) {
                Log.i("MyGesture", "onSingleTapUp");
                return true;
            }

            // 5. 用戶按下觸摸屏 & 拖動
            public boolean onScroll(MotionEvent e1, MotionEvent e2,
                                    float distanceX, float distanceY) {
                Log.i("MyGesture", "onScroll:");
                return true;
            }

            // 6. 用戶按下觸摸屏、快速移動後鬆開
            // 參數:
            // e1:第1個ACTION_DOWN MotionEvent
            // e2:最後一個ACTION_MOVE MotionEvent
            // velocityX:X軸上的移動速度,像素/秒
            // velocityY:Y軸上的移動速度,像素/秒
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                                   float velocityY) {
                Log.i("MyGesture", "onFling");
                return true;
            }

        });

        // 步驟2:讓TextView檢測手勢:重寫View的onTouch函數,將觸屏事件交給GestureDetector處理,從而對用戶手勢作出響應
        mTextView = (TextView) findViewById(R.id.textView);
        mTextView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                mGestureDetector.onTouchEvent(event);
                return false;
            }
        });
    }
}

4. 示意圖

我在屏幕作出一系列手勢進行測試


接口2:OnDoubleTapListener

1. 作用

檢測用戶單擊、雙擊屏幕

2. 使用步驟

// 步驟1:創建手勢檢測器實例
    // 注:使用OnDoubleTapListener接口時,需要使用GestureDetector,而GestureDetector的創建則必須傳入OnGestureListener接口
    // 所以在使用OnDoubleTapListener接口時,也必須實現OnGestureListener接口
    // 構造函數有3個,常用的是第二個
    // 1. GestureDetector gestureDetector=new GestureDetector(GestureDetector.OnGestureListener listener);
    // 2. GestureDetector gestureDetector=new GestureDetector(Context context,GestureDetector.OnGestureListener listener);
    // 3. GestureDetector gestureDetector=new GestureDetector(Context context,GestureDetector.SimpleOnGestureListener listener);
        GestureDetector mGestureDetector = new GestureDetector(this, new GestureDetector.OnGestureListener() {

            // 1. 用戶輕觸觸摸屏
            public boolean onDown(MotionEvent e) {
                Log.i("MyGesture", "onDown");
                return false;
            }

            // 2. 用戶輕觸觸摸屏,尚未鬆開或拖動
            // 與onDown()的區別:無鬆開 / 拖動
            // 即:當用戶點擊的時,onDown()就會執行,在按下的瞬間沒有鬆開 / 拖動時onShowPress就會執行
            public void onShowPress(MotionEvent e) {
                Log.i("MyGesture", "onShowPress");
            }

            // 3. 用戶長按觸摸屏
            public void onLongPress(MotionEvent e) {
                Log.i("MyGesture", "onLongPress");
            }

            // 4. 用戶輕擊屏幕後擡起
            public boolean onSingleTapUp(MotionEvent e) {
                Log.i("MyGesture", "onSingleTapUp");
                return true;
            }

            // 5. 用戶按下觸摸屏 & 拖動
            public boolean onScroll(MotionEvent e1, MotionEvent e2,
                                    float distanceX, float distanceY) {
                Log.i("MyGesture", "onScroll:");
                return true;
            }

            // 6. 用戶按下觸摸屏、快速移動後鬆開
            // 參數:
            // e1:第1個ACTION_DOWN MotionEvent
            // e2:最後一個ACTION_MOVE MotionEvent
            // velocityX:X軸上的移動速度,像素/秒
            // velocityY:Y軸上的移動速度,像素/秒
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                                   float velocityY) {
                Log.i("MyGesture", "onFling");
                return true;
            }

        });

// 步驟2:創建 & 設置OnDoubleTapListener接口實現類
    mGestureDetector.setOnDoubleTapListener(new GestureDetector.OnDoubleTapListener() {

        // 1. 單擊事件
        // 關於OnDoubleTapListener.onSingleTapConfirmed()和 OnGestureListener.onSingleTapUp()的區別
        // onSingleTapConfirmed:再次點擊(即雙擊),則不會執行
        // onSingleTapUp:手擡起就會執行
        public boolean onSingleTapConfirmed(MotionEvent e) {
            Log.i("MyGesture", "onSingleTapConfirmed");
            return false;
        }

        // 2. 雙擊事件
        public boolean onDoubleTap(MotionEvent e) {
            Log.i("MyGesture", "onDoubleTap");
            return false;
        }
        // 3. 雙擊間隔中發生的動作
        // 指觸發onDoubleTap後,在雙擊之間發生的其它動作,包含down、up和move事件;
        public boolean onDoubleTapEvent(MotionEvent e) {
            Log.i("MyGesture", "onDoubleTapEvent");
            return false;
        }
    });

// 步驟3-1:讓某個View檢測手勢 - 重寫View的onTouch函數,將View的觸屏事件交給GestureDetector處理,從而對用戶手勢作出響應
    View.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            mGestureDetector.onTouchEvent(event);
            return true; // 注:返回true才能完整接收觸摸事件
        }
    });

// 步驟3-2:讓某個Activity檢測手勢:重寫Activity的dispatchTouchEvent函數,將觸屏事件交給GestureDetector處理,從而對用戶手勢作出響應
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        mGestureDetector.onTouchEvent(ev); // 讓GestureDetector響應觸碰事件
        super.dispatchTouchEvent(ev); // 讓Activity響應觸碰事件
        return false;
    }

3. 實例說明

現在對一個TextView進行手勢檢測
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    >

    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="600dp"
        android:text="carson_ho Test"
        android:textAppearance="?android:attr/textAppearanceLarge" />

</LinearLayout>

MainActivity.java

public class MainActivity extends AppCompatActivity {

    TextView mTextView;
    GestureDetector mGestureDetector;

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

        // 步驟1:創建手勢檢測器實例 & 傳入OnGestureListener接口(需要複寫對應方法)
        mGestureDetector = new GestureDetector(this, new GestureDetector.OnGestureListener() {

            // 1. 用戶輕觸觸摸屏
            public boolean onDown(MotionEvent e) {
                Log.i("MyGesture1", "onDown");
                return false;
            }

            // 2. 用戶輕觸觸摸屏,尚未鬆開或拖動
            // 與onDown()的區別:無鬆開 / 拖動
            // 即:當用戶點擊的時,onDown()就會執行,在按下的瞬間沒有鬆開 / 拖動時onShowPress就會執行
            public void onShowPress(MotionEvent e) {
                Log.i("MyGesture", "onShowPress");
            }

            // 3. 用戶長按觸摸屏
            public void onLongPress(MotionEvent e) {
                Log.i("MyGesture", "onLongPress");
            }

            // 4. 用戶輕擊屏幕後擡起
            public boolean onSingleTapUp(MotionEvent e) {
                Log.i("MyGesture", "onSingleTapUp");
                return true;
            }

            // 5. 用戶按下觸摸屏 & 拖動
            public boolean onScroll(MotionEvent e1, MotionEvent e2,
                                    float distanceX, float distanceY) {
                Log.i("MyGesture", "onScroll:");
                return true;
            }

            // 6. 用戶按下觸摸屏、快速移動後鬆開
            // 參數:
            // e1:第1個ACTION_DOWN MotionEvent
            // e2:最後一個ACTION_MOVE MotionEvent
            // velocityX:X軸上的移動速度,像素/秒
            // velocityY:Y軸上的移動速度,像素/秒
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                                   float velocityY) {
                Log.i("MyGesture", "onFling");
                return true;
            }

        });

        // 步驟2:創建 & 設置OnDoubleTapListener接口實現類
        mGestureDetector.setOnDoubleTapListener(new GestureDetector.OnDoubleTapListener() {

            // 1. 單擊事件
            // 關於OnDoubleTapListener.onSingleTapConfirmed()和 OnGestureListener.onSingleTapUp()的區別
            // onSingleTapConfirmed:再次點擊(即雙擊),則不會執行
            // onSingleTapUp:手擡起就會執行
            public boolean onSingleTapConfirmed(MotionEvent e) {
                Log.i("MyGesture", "onSingleTapConfirmed");
                return false;
            }

            // 2. 雙擊事件
            public boolean onDoubleTap(MotionEvent e) {
                Log.i("MyGesture", "onDoubleTap");
                return false;
            }
            // 3. 雙擊間隔中發生的動作
            // 指觸發onDoubleTap後,在雙擊之間發生的其它動作,包含down、up和move事件;
            public boolean onDoubleTapEvent(MotionEvent e) {
                Log.i("MyGesture", "onDoubleTapEvent");
                return false;
            }
        });

        // 步驟3:重寫View的onTouch函數,將觸屏事件交給GestureDetector處理,從而對用戶手勢作出響應
        mTextView = (TextView) findViewById(R.id.textView);

        mTextView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                mGestureDetector.onTouchEvent(event);
                return true;
            }
        });
    }
}

4. 測試效果

日誌效果如下


使用類:SimpleOnGestureListener

1. 作用

集成了兩個接口的手勢檢測功能

2. 與上述兩個接口的區別

  • OnGestureListener和OnDoubleTapListener接口裏的函數都是強制必須重寫的
  • 而SimpleOnGestureListener類的函數則可根據需要選擇性複寫,因爲SimpleOnGestureListener類本身已經實現了這兩個接口的所有函數,只是裏面全是空的而已

3. 使用步驟

// 步驟1:創建手勢檢測器實例
    // 構造函數有3個,此處用的是第三個
    // 1. GestureDetector gestureDetector=new GestureDetector(GestureDetector.OnGestureListener listener);
    // 2. GestureDetector gestureDetector=new GestureDetector(Context context,GestureDetector.OnGestureListener listener);
    // 3. GestureDetector gestureDetector=new GestureDetector(Context context,GestureDetector.SimpleOnGestureListener listener);
    GestureDetector mGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {

        // OnGestureListener接口的函數
        // 1. 用戶輕觸觸摸屏
        public boolean onDown(MotionEvent e) {
            Log.i("MyGesture1", "onDown");
            return false;
        }

        // 2. 用戶輕觸觸摸屏,尚未鬆開或拖動
        // 與onDown()的區別:無鬆開 / 拖動
        // 即:當用戶點擊的時,onDown()就會執行,在按下的瞬間沒有鬆開 / 拖動時onShowPress就會執行
        public void onShowPress(MotionEvent e) {
            Log.i("MyGesture", "onShowPress");
        }

        // 3. 用戶長按觸摸屏
        public void onLongPress(MotionEvent e) {
            Log.i("MyGesture", "onLongPress");
        }

        // 4. 用戶輕擊屏幕後擡起
        public boolean onSingleTapUp(MotionEvent e) {
            Log.i("MyGesture", "onSingleTapUp");
            return true;
        }

        // 5. 用戶按下觸摸屏 & 拖動
        public boolean onScroll(MotionEvent e1, MotionEvent e2,
                                float distanceX, float distanceY) {
            Log.i("MyGesture", "onScroll:");
            return true;
        }

        // 6. 用戶按下觸摸屏、快速移動後鬆開
        // 參數:
        // e1:第1個ACTION_DOWN MotionEvent
        // e2:最後一個ACTION_MOVE MotionEvent
        // velocityX:X軸上的移動速度,像素/秒
        // velocityY:Y軸上的移動速度,像素/秒
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                               float velocityY) {
            Log.i("MyGesture", "onFling");
            return true;
        }

        // OnDoubleTapListener的函數
        // 1. 單擊事件
        // 關於OnDoubleTapListener.onSingleTapConfirmed()和 OnGestureListener.onSingleTapUp()的區別
        // onSingleTapConfirmed:再次點擊(即雙擊),則不會執行
        // onSingleTapUp:手擡起就會執行
        public boolean onSingleTapConfirmed(MotionEvent e) {
            Log.i("MyGesture", "onSingleTapConfirmed");
            return false;
        }

        // 2. 雙擊事件
        public boolean onDoubleTap(MotionEvent e) {
            Log.i("MyGesture", "onDoubleTap");
            return false;
        }
        // 3. 雙擊間隔中發生的動作
        // 指觸發onDoubleTap後,在雙擊之間發生的其它動作,包含down、up和move事件;
        public boolean onDoubleTapEvent(MotionEvent e) {
            Log.i("MyGesture", "onDoubleTapEvent");
            return false;
        }
    });

// 步驟2-1:讓某個View檢測手勢 - 重寫View的onTouch函數,將View的觸屏事件交給GestureDetector處理,從而對用戶手勢作出響應
    View.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            mGestureDetector.onTouchEvent(event);
            return true; // 注:返回true才能完整接收觸摸事件
        }
    });

// 步驟2-2:讓某個Activity檢測手勢:重寫Activity的dispatchTouchEvent函數,將觸屏事件交給GestureDetector處理,從而對用戶手勢作出響應
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        mGestureDetector.onTouchEvent(ev); // 讓GestureDetector響應觸碰事件
        super.dispatchTouchEvent(ev); // 讓Activity響應觸碰事件
        return false;
    }

4. 實例說明

現在對一個TextView進行手勢檢測
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    >

    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="600dp"
        android:text="carson_ho Test"
        android:textAppearance="?android:attr/textAppearanceLarge" />

</LinearLayout>

MainActivity.java

public class MainActivity extends AppCompatActivity {

    TextView mTextView;
    GestureDetector mGestureDetector;

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

        // 步驟1:創建手勢檢測器實例 & 傳入OnGestureListener接口(需要複寫對應方法)
        mGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {

            // OnGestureListener接口的函數
            // 1. 用戶輕觸觸摸屏
            public boolean onDown(MotionEvent e) {
                Log.i("MyGesture1", "onDown");
                return false;
            }

            // 2. 用戶輕觸觸摸屏,尚未鬆開或拖動
            // 與onDown()的區別:無鬆開 / 拖動
            // 即:當用戶點擊的時,onDown()就會執行,在按下的瞬間沒有鬆開 / 拖動時onShowPress就會執行
            public void onShowPress(MotionEvent e) {
                Log.i("MyGesture", "onShowPress");
            }

            // 3. 用戶長按觸摸屏
            public void onLongPress(MotionEvent e) {
                Log.i("MyGesture", "onLongPress");
            }

            // 4. 用戶輕擊屏幕後擡起
            public boolean onSingleTapUp(MotionEvent e) {
                Log.i("MyGesture", "onSingleTapUp");
                return true;
            }

            // 5. 用戶按下觸摸屏 & 拖動
            public boolean onScroll(MotionEvent e1, MotionEvent e2,
                                    float distanceX, float distanceY) {
                Log.i("MyGesture", "onScroll:");
                return true;
            }

            // 6. 用戶按下觸摸屏、快速移動後鬆開
            // 參數:
            // e1:第1個ACTION_DOWN MotionEvent
            // e2:最後一個ACTION_MOVE MotionEvent
            // velocityX:X軸上的移動速度,像素/秒
            // velocityY:Y軸上的移動速度,像素/秒
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                                   float velocityY) {
                Log.i("MyGesture", "onFling");
                return true;
            }

            // OnDoubleTapListener的函數
            // 1. 單擊事件
            // 關於OnDoubleTapListener.onSingleTapConfirmed()和 OnGestureListener.onSingleTapUp()的區別
            // onSingleTapConfirmed:再次點擊(即雙擊),則不會執行
            // onSingleTapUp:手擡起就會執行
            public boolean onSingleTapConfirmed(MotionEvent e) {
                Log.i("MyGesture", "onSingleTapConfirmed");
                return false;
            }

            // 2. 雙擊事件
            public boolean onDoubleTap(MotionEvent e) {
                Log.i("MyGesture", "onDoubleTap");
                return false;
            }
            // 3. 雙擊間隔中發生的動作
            // 指觸發onDoubleTap後,在雙擊之間發生的其它動作,包含down、up和move事件;
            public boolean onDoubleTapEvent(MotionEvent e) {
                Log.i("MyGesture", "onDoubleTapEvent");
                return false;
            }
        });

        // 步驟2:重寫View的onTouch函數,將觸屏事件交給GestureDetector處理,從而對用戶手勢作出響應
        mTextView = (TextView) findViewById(R.id.textView);
        mTextView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                mGestureDetector.onTouchEvent(event);
                return true;
            }
        });
    }
}

5. 測試效果

日誌效果如下

至此,關於Android手勢識別類GestureDetector類使用講解完畢。


總結

  • 本文主要對Android手勢識別類:GestureDetector類的使用進行全面講解
  • 接下來我將繼續介紹 Android開發中的相關知識,感興趣的同學可以繼續關注本人博客Carson_Ho的開發筆記

請幫頂 / 評論 點贊!因爲你的鼓勵是我寫作的最大動力!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章