简体   繁体   English

在 Android 中获取 onTouch ACTION_MOVE 事件的速度

[英]Get speed of a onTouch ACTION_MOVE event in Android

This should be a pretty simple thing to do.这应该是一件非常简单的事情。 The user puts his finger on the screen and drags it around the screen.用户将手指放在屏幕上并在屏幕上拖动。 There are two events firing on onTouch: onTouch 上触发了两个事件:

  • MotionEvent.ACTION_DOWN MotionEvent.ACTION_DOWN
  • MotionEvent.ACTION_MOVE MotionEvent.ACTION_MOVE

Now, how can I calculate the speed of the ACTION_MOVE gesture?现在,如何计算 ACTION_MOVE 手势的速度? The user drags the finger slower or faster during a gesture, so I think I need to calculate the speed between two intermediate touched points: the lastTouchedPointX,lastTouchedPointY and the event.getX(),event.getY().用户在手势过程中拖动手指的速度变慢或变快,所以我想我需要计算两个中间触摸点之间的速度:lastTouchedPointX,lastTouchedPointY 和 event.getX(),event.getY()。

Has anyone done this before?有没有人这样做过?

What you need can be achieved by using the standard VelocityTracker class.使用标准VelocityTracker class 可以实现您所需要的。 More details on Google's Best Practice for User Input while tracking movement here .有关 Google 在跟踪移动时的用户输入最佳实践的更多详细信息,请点击此处 Most of the code below (which demonstrates the use of VelocityTracker by displaying the speed on X and Y axis of each fling/move) is taken from the previous resource link:下面的大部分代码(通过在 X 和 Y 轴上显示每个投掷/移动的速度来演示VelocityTracker的使用)取自之前的资源链接:

import android.os.Bundle;
import android.app.Activity;
import android.support.v4.view.VelocityTrackerCompat;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.widget.TextView;

public class MainActivity extends Activity {

    private VelocityTracker mVelocityTracker = null;
    private TextView mTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mTextView = new TextView(this);
        mTextView.setText("Move finger on screen to get velocity.");
        setContentView(mTextView);
    }

    @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.
            mTextView.setText("X velocity: "
                    + VelocityTrackerCompat.getXVelocity(mVelocityTracker,
                            pointerId)
                    + "\nY velocity: "
                    + VelocityTrackerCompat.getYVelocity(mVelocityTracker,
                            pointerId));
            break;
        case MotionEvent.ACTION_UP:
            break;
        case MotionEvent.ACTION_CANCEL:
            // Return a VelocityTracker object back to be re-used by others.
            mVelocityTracker.recycle();
            break;
        }
        return true;
    }

}
@Override
        public boolean onTouchEvent(MotionEvent event, MapView mapView) {


            if(event.getAction() == MotionEvent.ACTION_DOWN) {

                oldX = event.getX();
                oldY = event.getY();
                    //start timer

            } else if (event.getAction() == MotionEvent.ACTION_UP) {   

                //long timerTime = getTime between two event down to Up
                newX = event.getX();
                newY = event.getY();

                float distance = Math.sqrt((newX-oldX) * (newX-oldX) + (newY-oldY) * (newY-oldY));
                float speed = distance / timerTime;

            }
}

It's a question about how accurate you want to perform this calculation.这是一个关于您希望执行此计算的准确度的问题。

However the basic procedure is to get the timestamp of each corresponding ACTION_DOWN, ACTION_UP couple and calculate the difference.然而基本过程是获取每个对应的 ACTION_DOWN、ACTION_UP 对的时间戳并计算差异。

Then you need to determine the covered pixels.然后你需要确定被覆盖的像素。 This could be done with simple trigonometry.这可以通过简单的三角函数来完成。

When you have both time difference and covered pixels you can calculate the pixels per time speed as an average of the two points (down and up).当您同时具有时差和覆盖像素时,您可以将每个时间速度的像素计算为两个点(向下和向上)的平均值。

You can do this for every point when the finger is moving over the screen to get a better result.当手指在屏幕上移动时,您可以对每个点执行此操作以获得更好的结果。

Image in Canvas with touch events from this example get touch event time & calculate time & distance to get speed Canvas 中的图像与此示例中的触摸事件获取触摸事件时间并计算时间和距离以获取速度

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM