タップとポインタの動きをトラッキングする

Compose を試す
Jetpack Compose は、Android に推奨される UI ツールキットです。Compose でタップと入力を使用する方法について学習します。
<ph type="x-smartling-placeholder"></ph> ジェスチャー →

このレッスンでは、タッチイベントの動きをトラッキングする方法について説明します。

新しい onTouchEvent() トリガーされる ACTION_MOVE 件の予定 現在のタッチ接触位置、圧力、サイズが変化したとき。として 一般的なジェスチャーを検出するで説明されているとおりに、 これらのイベントは MotionEvent パラメータ: onTouchEvent()

指によるタップは必ずしも正確な操作方法ではないので、 タッチイベントの検出は、単純な接触ではなく、動きに基づいて行われることがよくあります。 アプリが動きベースの操作(スワイプなど)と 非移動操作(シングルタップなど)に加え、Android には タッチスロップ。タッチスロップとはユーザーのタップ操作の距離(ピクセル単位)です 動作ベースのジェスチャーとして解釈される前になぞる必要があることを意味します。詳細 このトピックについて詳しくは、 ViewGroup

ジェスチャーの動きを追跡する方法はいくつかあり、 アプリケーションのニーズに 対応できます以下に例を示します。

  • ポインタの開始位置と終了位置(画面上の移動など) 対象物をポイント A からポイント B に移動させます。
  • X と Y で決定されるポインタの進行方向 指定します。
  • 履歴。ジェスチャーの履歴のサイズは、 MotionEvent メソッド getHistorySize()。 これにより、各画像のポジション、サイズ、時間、圧力を モーションイベントの getHistorical<Value> あります。履歴は、ユーザーの指の跡をレンダリングする際に役立ちます。 タップで描画します詳細については、MotionEvent のリファレンスをご覧ください。
  • タッチスクリーン上を移動する際のポインタの速度。

以下の関連リソースもご覧ください。

トラッキング速度

距離や方向に基づいた動きベースのジェスチャー 移動します。ただし、多くの場合、速度は追跡の決定要因になります。 特定の操作が行われたかどうかの判断などです。 簡単になったため、Android には VelocityTracker クラス。 VelocityTracker は、タッチイベントの速度を追跡するのに役立ちます。役に立った 速度がジェスチャーの基準の一部であるジェスチャーの場合: できます。

次に、 VelocityTracker API:

Kotlin

private const val DEBUG_TAG = "Velocity"

class MainActivity : Activity() {
    private var mVelocityTracker: VelocityTracker? = null

    override fun onTouchEvent(event: MotionEvent): Boolean {

        when (event.actionMasked) {
            MotionEvent.ACTION_DOWN -> {
                // Reset the velocity tracker back to its initial state.
                mVelocityTracker?.clear()
                // If necessary, retrieve a new VelocityTracker object to watch
                // the velocity of a motion.
                mVelocityTracker = mVelocityTracker ?: VelocityTracker.obtain()
                // Add a user's movement to the tracker.
                mVelocityTracker?.addMovement(event)
            }
            MotionEvent.ACTION_MOVE -> {
                mVelocityTracker?.apply {
                    val pointerId: Int = event.getPointerId(event.actionIndex)
                    addMovement(event)
                    // When you want to determine the velocity, call
                    // computeCurrentVelocity(). Then, call getXVelocity() and
                    // getYVelocity() to retrieve the velocity for each pointer
                    // ID.
                    computeCurrentVelocity(1000)
                    // Log velocity of pixels per second. It's best practice to
                    // use VelocityTrackerCompat where possible.
                    Log.d("", "X velocity: ${getXVelocity(pointerId)}")
                    Log.d("", "Y velocity: ${getYVelocity(pointerId)}")
                }
            }
            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                // Return a VelocityTracker object back to be re-used by others.
                mVelocityTracker?.recycle()
                mVelocityTracker = null
            }
        }
        return true
    }
}

Java

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. It's best practice to use
                // VelocityTrackerCompat where possible.
                Log.d("", "X velocity: " + mVelocityTracker.getXVelocity(pointerId));
                Log.d("", "Y velocity: " + mVelocityTracker.getYVelocity(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;
    }
}

ポインタ キャプチャの使用

ゲーム、リモート デスクトップ、仮想化クライアントなど、一部のアプリには、 制御できないようにします。ポインタ キャプチャは Android 8.0(API レベル 26)以降では、Android 8.0(API レベル 26)以降で アプリ内のフォーカスされたビューにすべてのマウスイベントを配信します。

ポインタ キャプチャのリクエスト

アプリ内のビューがポインタのキャプチャをリクエストできるのは、 フォーカスがあります。このため、ポインタのキャプチャをリクエストするのは、 ビューに対する特定のユーザー アクション(たとえば、 onClick() イベントで onWindowFocusChanged() アクティビティのイベント ハンドラを作成します。

ポインタのキャプチャをリクエストするには、 requestPointerCapture() メソッドを呼び出します。次のコードサンプルは、ポインタをリクエストする方法を示しています。 ユーザーがビューをクリックしたときにキャプチャします。

Kotlin

fun onClick(view: View) {
    view.requestPointerCapture()
}

Java

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

ポインタをキャプチャするリクエストが成功すると、Android は以下を呼び出します。 onPointerCaptureChange(true)。 次の限り、マウスイベントがアプリのフォーカスされているビューに配信されます。 キャプチャをリクエストしたビューと同じビュー階層にある。その他 キャプチャがリリースされるまで、マウスイベントの受信が停止されます。 ACTION_OUTSIDE できます。Android では、マウス以外のソースからのポインタ イベントを マウスポインタは非表示になりますが、

キャプチャされたポインタ イベントの処理

ビューがポインタのキャプチャを正常に取得すると、Android は 使用できます。フォーカスしたビューで、次のいずれかを実行してイベントを処理できます。 できます。

次のコード例は、 onCapturedPointerEvent(MotionEvent):

Kotlin

override fun onCapturedPointerEvent(motionEvent: MotionEvent): Boolean {
    // Get the coordinates required by your app.
    val verticalOffset: Float = motionEvent.y
    // Use the coordinates to update your view and return true if the event is
    // successfully processed.
    return true
}

Java

@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 is
  // successfully processed.
  return true;
}

次のコードサンプルは、 OnCapturedPointerListener:

Kotlin

myView.setOnCapturedPointerListener { view, motionEvent ->
    // Get the coordinates required by your app.
    val horizontalOffset: Float = motionEvent.x
    // Use the coordinates to update your view and return true if the event is
    // successfully processed.
    true
}

Java

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 is
    // successfully processed.
    return true;
  }
});

カスタムビューを使用する場合でもリスナーを登録する場合でも、ビューは MotionEvent は、X などの相対移動を指定するポインタ座標に置き換えます Y デルタ(トラックボール デバイスによって配信される座標に類似)Google Chat では 座標を取得するには、 getX()getY()

ポインタ キャプチャの解除

アプリのビューは、次の呼び出しによってポインタのキャプチャを解放できます。 releasePointerCapture() これを次のサンプルコードに示します。

Kotlin

override fun onClick(view: View) {
    view.releasePointerCapture()
}

Java

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

ユーザーが明示的に指定しなくても、システムによってキャプチャがビューから取り除かれることがある releasePointerCapture() の呼び出し。これは通常、ビュー階層が ビューが含まれていると、フォーカスが失われます。