【Touch&input 】跟蹤觸摸和指針移動(5)

本課介紹如何跟蹤觸摸事件中的移動。

每當當前觸摸位置,壓力或尺寸改變時,都會onTouchEvent()觸發一個新ACTION_MOVE事件。如“ 檢測常見手勢”中所述,所有這些事件都記錄在MotionEvent參數中onTouchEvent()。

因爲基於手指的觸摸並不總是最精確的交互形式,所以檢測觸摸事件通常更多地基於移動而不是簡單的接觸。爲了幫助應用程序區分基於移動的手勢(例如滑動手勢)和非移動手勢(例如單擊),Android包含“觸摸斜倚”的概念。觸摸斜率指的是在手勢被解釋爲基於移動的手勢之前用戶的觸摸可以漫遊的像素距離。有關此主題的更多討論,請參閱管理ViewGroup中的觸摸事件

根據應用程序的需要,有幾種不同的方式可以跟蹤手勢中的移動。例如:

  • 指針的開始和結束位置(例如,將屏幕上的對象從A點移動到B點)。
  • 指針正在行進的方向,由x和y座標確定。
  • 歷史。您可以通過調用該MotionEvent方法來查找手勢歷史記錄的大小getHistorySize()。然後,您可以使用運動事件的 方法獲取每個歷史事件的位置,大小,時間和壓力。繪製用戶手指的軌跡時,歷史記錄很有用,例如觸摸繪圖。詳情請參閱參考資料。getHistorical<Value>MotionEvent
  • 指針在移動觸摸屏時的速度。

請參閱以下相關資源:

跟蹤速度


您可以擁有一個基於運動的手勢,該手勢僅基於指針行進的距離和/或方向。但速度往往是跟蹤手勢特徵或決定手勢是否發生的決定性因素。爲了讓速度計算更容易,Android提供了這個 VelocityTracker類。VelocityTracker幫助您追蹤觸摸事件的速度。這對於速度是手勢標準的一部分的手勢很有用,例如一甩手。

以下是一個簡單的例子,說明VelocityTrackerAPI中方法的用途 :

public class MainActivity extends Activity {
    private static final String DEBUG_TAG = "Velocity";
        ...
    private VelocityTracker mVelocityTracker = null;
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int index = event.getActionIndex();
        int action = event.getActionMasked();
        int pointerId = event.getPointerId(index);

        switch(action) {
            case MotionEvent.ACTION_DOWN:
                if(mVelocityTracker == null) {
                    // Retrieve a new VelocityTracker object to watch the
                    // velocity of a motion.
                    mVelocityTracker = VelocityTracker.obtain();
                }
                else {
                    // Reset the velocity tracker back to its initial state.
                    mVelocityTracker.clear();
                }
                // Add a user's movement to the tracker.
                mVelocityTracker.addMovement(event);
                break;
            case MotionEvent.ACTION_MOVE:
                mVelocityTracker.addMovement(event);
                // When you want to determine the velocity, call
                // computeCurrentVelocity(). Then call getXVelocity()
                // and getYVelocity() to retrieve the velocity for each pointer ID.
                mVelocityTracker.computeCurrentVelocity(1000);
                // Log velocity of pixels per second
                // Best practice to use VelocityTrackerCompat where possible.
                Log.d("", "X velocity: " +
                        VelocityTrackerCompat.getXVelocity(mVelocityTracker,
                        pointerId));
                Log.d("", "Y velocity: " +
                        VelocityTrackerCompat.getYVelocity(mVelocityTracker,
                        pointerId));
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                // Return a VelocityTracker object back to be re-used by others.
                mVelocityTracker.recycle();
                break;
        }
        return true;
    }
}

注意:你應該在ACTION_MOVE事件之後計算速度,而不是之後ACTION_UP。之後ACTION_UP,X和Y速度將爲0。

使用指針捕獲


某些應用程序(如遊戲,遠程桌面和虛擬化客戶端)通過控制鼠標指針獲益匪淺。指針捕獲是Android 8.0(API級別26)中提供的一項功能,稍後通過將所有鼠標事件提供給應用程序中的焦點視圖來提供此類控制

請求指針捕獲

只有當包含它的視圖層次結構具有焦點時,您的應用中的視圖才能請求指針捕獲。出於這個原因,當視圖上存在特定的用戶操作時(例如在onClick()事件期間或在onWindowFocusChanged()您的活動的事件處理程序中),您應該請求指針捕獲。

要請求捕獲指針,請調用requestPointerCapture()視圖上的方法。下面的代碼示例演示如何在用戶單擊視圖時請求指針捕獲:

@Override
public void onClick(View view) {
    view.requestPointerCapture();
}

一旦捕獲指針的請求成功,Android就會調用onPointerCaptureChange(true)。只要與請求捕獲的視圖位於相同的視圖層次結構中,系統就會將鼠標事件傳遞到應用程序中的焦點視圖。其他應用程序停止接收鼠標事件,直到發佈捕獲,包括ACTION_OUTSIDE事件。Android通常從鼠標以外的其他來源傳遞指針事件,但鼠標指針不再可見。

處理捕獲的指針事件

一旦視圖成功獲取指針捕獲,Android就開始提供鼠標事件。您關注的視圖可以通過執行以下任務之一來處理事件:

  1. 如果您使用自定義視圖,請覆蓋onCapturedPointerEvent(MotionEvent)。
  2. 否則,註冊一個OnCapturedPointerListener。

以下代碼示例演示如何實現onCapturedPointerEvent(MotionEvent):

@Override
public boolean onCapturedPointerEvent(MotionEvent motionEvent) {
  // Get the coordinates required by your app
  float verticalOffset = motionEvent.getY();
  // Use the coordinates to update your view and return true if the event was
  // successfully processed
  return true;
}

以下代碼示例顯示如何註冊一個OnCapturedPointerListener:

myView.setOnCapturedPointerListener(new View.OnCapturedPointerListener() {
  @Override
  public boolean onCapturedPointer (View view, MotionEvent motionEvent) {
    // Get the coordinates required by your app
    float horizontalOffset = motionEvent.getX();
    // Use the coordinates to update your view and return true if the event was
    // successfully processed
    return true;
  }
});

無論您使用自定義視圖還是註冊偵聽器,您的視圖都會接收到一個 MotionEvent指針座標,用於指定相對移動,如X / Y增量,類似於由軌跡球設備提供的座標。您可以使用getX()和檢索座標getY()。

釋放指針捕獲

您的應用中的視圖可以通過調用釋放指針捕獲releasePointerCapture(),如以下代碼示例所示:

@Override
public void onClick(View view) {
    view.releasePointerCapture();
}

系統可以在沒有明確調用的情況下將捕獲從視圖中移除releasePointerCapture(),這通常是因爲包含請求捕獲的視圖的視圖層次結構失去了焦點。

Lastest Update:2018.04.25

聯繫我

QQ:94297366
微信打賞:https://pan.baidu.com/s/1dSBXk3eFZu3mAMkw3xu9KQ

公衆號推薦:

【Touch&input 】跟蹤觸摸和指針移動(5)

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