【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)

猜你喜欢

转载自blog.51cto.com/4789781/2124895
今日推荐