Android小总结:VelocityTracker

VelocityTracker是Android中用于追踪触摸事件速率的工具,适用于检测滑动和其他手势。通过VelocityTracker.obtain()获取实例,然后在ACTION_DOWN、ACTION_MOVE和ACTION_UP事件中添加MotionEvent。在ACTION_MOVE和ACTION_UP中可以获取X轴速度,从而实现速度检测功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

VelocityTracker是一个什么东西呢,查看VelocityTracker源代码发现有如下注释:

 /**
     * Helper for tracking the velocity of touch events, for implementing
     * flinging and other such gestures.
     *
     * Use {@link #obtain} to retrieve a new instance of the class when you are going
     * to begin tracking.  Put the motion events you receive into it with
     * {@link #addMovement(android.view.MotionEvent)}.  When you want to determine the velocity call
     * {@link #computeCurrentVelocity(int)} and then call {@link #getXVelocity(int)}
     * and {@link #getYVelocity(int)} to retrieve the velocity for each pointer id.
     *
     * 追踪触摸事件速率,实现flinging和其他手势的帮助类
     *
     * 1、当开始追踪的时候,使用obtain来获取VelocityTracker类的实例
     * 2、把接收到的MotionEvent放入到addMovement(android.view.MotionEvent)中
     * 3、当要确定速度时调用computeCurrentVelocity(int),
     *   使用getXVelocity(int)和getYVelocity(int)来检测每个触摸点id的速率
     */

VelocityTracker是一个帮助追踪触摸事件速率的追踪器,可以追踪fliinging和其他触摸手势。

如何使用VelocityTracker呢,注释中提到如下步骤:

     1、当开始追踪的时候,使用obtain来获取VelocityTracker类的实例
     2、把接受到的MotionEvent放入到addMovement(android.view.MotionEvent)中
     3、当要确定速度时调用computeCurrentVelocity(int),
           使用getXVelocity(int)和getYVelocity(int)来检测每个触摸点id的速率

既然VelocityTracker是追踪触摸事件的速度追踪器,当然需要与触摸事件结合使用。

第一步:当你想要追踪触摸事件的速度时,使用private VelocityTracker mVelocityTracker = VelocityTracker.obtain();来获取一个实例,

obtain()方法的源代码:

   /**
     * Retrieve a new VelocityTracker object to watch the velocity of a
     * motion.  Be sure to call {@link #recycle} when done.  You should
     * generally only maintain an active object while tracking a movement,
     * so that the VelocityTracker can be re-used elsewhere.
     *
     * @return Returns a new VelocityTracker.
     *
     * 获取一个新的VelocityTracker对象,用于检测一个动作的速率
     * 检测结束时确保调用了recycle()方法来回收VelocityTracker对象
     * 追踪一个移动事件时通常只需要维护一个活动对象,这样VelocityTracker可以被重用
     */
    static public VelocityTracker obtain() {
        VelocityTracker instance = sPool.acquire();
        return (instance != null) ? instance : new VelocityTracker(null);
    }

第二步:把接收到的MotionEvent放入到addMovement(MotionEvent event)方法中,

在初始化MotionEvent的ACTION_DOWN时调用addMovement(MotionEvent event)

然后在ACTION_MOVE和ACTION_UP动作中就可以检测到速度了。

 /**
     * Add a user's movement to the tracker.  You should call this for the
     * initial {@link MotionEvent#ACTION_DOWN}, the following
     * {@link MotionEvent#ACTION_MOVE} events that you receive, and the
     * final {@link MotionEvent#ACTION_UP}.  You can, however, call this
     * for whichever events you desire.
     *
     * @param event The MotionEvent you received and would like to track.
     *
     * 添加一个移动事件到追踪器
     * 1.为初始化MotionEvent的ACTION_DOWN动作调用addMovement()
     * 2.接下来,在MotionEvent的ACTION_MOVE和ACTION_UP动作中接收。
     *    不管是哪一个events都可以调用本方法
     */
    public void addMovement(MotionEvent event) {
        if (event == null) {
            throw new IllegalArgumentException("event must not be null");
        }
        nativeAddMovement(mPtr, event);
    }

第三步:想要确定速度的时候调用computeCurrentVelocity(int units)方法。有两个同样的方法,一个带有最大值参数,默认为Float.MAX_VALUE

    /**
     * Compute the current velocity based on the points that have been
     * collected.  Only call this when you actually want to retrieve velocity
     * information, as it is relatively expensive.  You can then retrieve
     * the velocity with {@link #getXVelocity()} and
     * {@link #getYVelocity()}.
     * 根据收集到的触摸点计算当前速率
     * 因为此方法相当消耗性能,所以只有当真的确实想要检测速度信息的时候才调用这个方法
     * 然后可以通过getXVelocity()和getYVelocity()方法获取到追踪的速度
     *
     * @param units The units you would like the velocity in.  A value of 1
     * provides pixels per millisecond, 1000 provides pixels per second, etc.
     *        units :代表速度的单位,
     *              值为1时:代表每毫秒运动一个像素,px/ms
     *              值为1000时:代表每秒运动1000个像素,1000px/s
     * @param maxVelocity The maximum velocity that can be computed by this method.
     * This value must be declared in the same unit as the units parameter. This value
     * must be positive.
     *        maxVelocity :代表可以被本方法计算的最大速度,
     *                    这个值必须用同一个作为速度参数的单位声明,而且值必须为正数
     */
    public void computeCurrentVelocity(int units, float maxVelocity) {
        nativeComputeCurrentVelocity(mPtr, units, maxVelocity);
    }

 /**
     * Equivalent to invoking {@link #computeCurrentVelocity(int, float)} with a maximum
     * velocity of Float.MAX_VALUE.
     *
     * @see #computeCurrentVelocity(int, float)
     * 
     * 等价调用带有最大值为Float.MAX_VALUE的computeCurrentVelocity(int, float)方法,
     */
    public void computeCurrentVelocity(int units) {
        nativeComputeCurrentVelocity(mPtr, units, Float.MAX_VALUE);
    }

第四步:使用getXVelocity()和getYVelocity()方法获取检测到的速度

获取X轴方向的速度:

 /**
     * Retrieve the last computed X velocity.  You must first call
     * {@link #computeCurrentVelocity(int)} before calling this function.
     * 
     * 检测最后计算的X轴方向的速度,在调用getXVelocity()之前必须先调用computeCurrentVelocity(int)
     * @return The previously computed X velocity.
     */
    public float getXVelocity() {
        return nativeGetXVelocity(mPtr, ACTIVE_POINTER_ID);
    }
获取Y轴方向上的速度:
/**
     * Retrieve the last computed Y velocity.  You must first call
     * {@link #computeCurrentVelocity(int)} before calling this function.
     *
     * 检测最后计算的X轴方向的速度,在调用getXVelocity()之前必须先调用computeCurrentVelocity(int)
     * @return The previously computed Y velocity.
     */
    public float getYVelocity() {
        return nativeGetYVelocity(mPtr, ACTIVE_POINTER_ID);
    }

第五步:回收VelocityTracker实例

  /**
     * Return a VelocityTracker object back to be re-used by others.  You must
     * not touch the object after calling this function.
     *
     * 回收一个VelocityTracker对象给其他动作事件使用
     * 在调用recycle()这个函数之后,你不能访问VelocityTracker对象
     */
    public void recycle() {
        if (mStrategy == null) {
            clear();
            sPool.release(this);
        }
    }


小实例:

package com.zwc.admin.scrollerdemo;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;


public class VelocityTrackerTestActivity extends ActionBarActivity {

    private static final String TAG = "VelocityTrackerTestActivity";

    private VelocityTracker mVelocityTracker;
    private int mPointerId;

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

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction();
        if (null == mVelocityTracker) {
            mVelocityTracker = VelocityTracker.obtain();
        }
        mVelocityTracker.addMovement(event);
        
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                //获取第一个触摸点的id
                mPointerId = event.getPointerId(0);
                break;

            case MotionEvent.ACTION_MOVE:
                mVelocityTracker.computeCurrentVelocity(1000);
                float xVelocity = mVelocityTracker.getXVelocity(event.getPointerId(mPointerId));
                float yVelocity = mVelocityTracker.getYVelocity(event.getPointerId(mPointerId));
                Log.e(TAG, "xVelocity = " + xVelocity + ",yVelocity = " + yVelocity);
                break;

            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                if (null != mVelocityTracker) {
                    mVelocityTracker.recycle();
                }
                break;
        }

        return super.onTouchEvent(event);
    }

}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值