/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.view;
import android.util.Pools.SynchronizedPool;
/**
* 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(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.
*/
public final class VelocityTracker {
private static final SynchronizedPool sPool =
new SynchronizedPool(2);
private static final int ACTIVE_POINTER_ID = -1;
private long mPtr;// 获取到的速度跟踪器的ID?
private final String mStrategy;
private static native long nativeInitialize(String strategy);
private static native void nativeDispose(long ptr);
private static native void nativeClear(long ptr);
private static native void nativeAddMovement(long ptr, MotionEvent event);
private static native void nativeComputeCurrentVelocity(long ptr, int units, float maxVelocity);
private static native float nativeGetXVelocity(long ptr, int id);
private static native float nativeGetYVelocity(long ptr, int id);
private static native boolean nativeGetEstimator(long ptr, int id, Estimator outEstimator);
/**
* 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.
*/
static public VelocityTracker obtain() {
VelocityTracker instance = sPool.acquire();
return (instance != null) ? instance : new VelocityTracker(null);
}
/**
* Obtains a velocity tracker with the specified strategy.
* For testing and comparison purposes only.
*
* @param strategy The strategy, or null to use the default.
* @return The velocity tracker.
*
* @hide
*/
public static VelocityTracker obtain(String strategy) {
if (strategy == null) {
return obtain();
}
return new VelocityTracker(strategy);
}
/**
* Return a VelocityTracker object back to be re-used by others. You must
* not touch the object after calling this function.
*/
public void recycle() {
if (mStrategy == null) {
clear();
sPool.release(this);
}
}
private VelocityTracker(String strategy) {
mPtr = nativeInitialize(strategy);
mStrategy = strategy;
}
@Override
protected void finalize() throws Throwable {
try {
if (mPtr != 0) {
nativeDispose(mPtr);
mPtr = 0;
}
} finally {
super.finalize();
}
}
/**
* Reset the velocity tracker back to its initial state.
*/
public void clear() {
nativeClear(mPtr);
}
/**
* 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.
*/
public void addMovement(MotionEvent event) {
if (event == null) {
throw new IllegalArgumentException("event must not be null");
}
nativeAddMovement(mPtr, event);
}
/**
* Equivalent to invoking {@link #computeCurrentVelocity(int, float)} with a maximum
* velocity of Float.MAX_VALUE.
*
* @see #computeCurrentVelocity(int, float)
*/
public void computeCurrentVelocity(int units) {
nativeComputeCurrentVelocity(mPtr, 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()}.
* 根据收集到的点计算当前的速度。此方法比较 relatively expensive 耗时?
*
* @param units The units you would like the velocity in. A value of 1
* provides pixels per millisecond, 1000 provides pixels per second, etc.
* 值1表示每毫秒的像素,值1000表示每秒钟的像素,等等。
* @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.
* 此值必须在与units参数相同的单元中声明
*/
public void computeCurrentVelocity(int units, float maxVelocity) {
nativeComputeCurrentVelocity(mPtr, units, maxVelocity);
}
/**
* Retrieve the last computed X velocity. You must first call
* {@link #computeCurrentVelocity(int)} before calling this function.
*
* @return The previously computed X velocity.
*/
public float getXVelocity() {
return nativeGetXVelocity(mPtr, ACTIVE_POINTER_ID);
}
/**
* Retrieve the last computed Y velocity. You must first call
* {@link #computeCurrentVelocity(int)} before calling this function.
*
* @return The previously computed Y velocity.
*/
public float getYVelocity() {
return nativeGetYVelocity(mPtr, ACTIVE_POINTER_ID);
}
/**
* Retrieve the last computed X velocity. You must first call
* {@link #computeCurrentVelocity(int)} before calling this function.
*
* @param id Which pointer's velocity to return.
* @return The previously computed X velocity.
*/
public float getXVelocity(int id) {
return nativeGetXVelocity(mPtr, id);
}
/**
* Retrieve the last computed Y velocity. You must first call
* {@link #computeCurrentVelocity(int)} before calling this function.
*
* @param id Which pointer's velocity to return.
* @return The previously computed Y velocity.
*/
public float getYVelocity(int id) {
return nativeGetYVelocity(mPtr, id);
}
/**
* Get an estimator for the movements of a pointer using past movements of the
* pointer to predict future movements.
* 使用指针过去的运动来预测未来的运动,获得指针运动的估计量
*
* It is not necessary to call {@link #computeCurrentVelocity(int)} before calling
* this method.
*
* @param id Which pointer's velocity to return.
* @param outEstimator The estimator to populate. 要填充的估值器
* @return True if an estimator was obtained, false if there is no information
* available about the pointer.
* 如果得到一个估计值,则为真;如果没有可用的指针信息,则为假
*
* @hide For internal use only. Not a final API.
*/
public boolean getEstimator(int id, Estimator outEstimator) {
if (outEstimator == null) {
throw new IllegalArgumentException("outEstimator must not be null");
}
return nativeGetEstimator(mPtr, id, outEstimator);
}
/**
* An estimator for the movements of a pointer based on a polynomial model.
* 基于多项式模型的指针运动估计器
*
* The last recorded position of the pointer is at time zero seconds.
* 指针的最后记录位置是在零时秒
* Past estimated positions are at negative times and future estimated positions
* are at positive times.
* 过去的估计位置处于负时区,而未来的估计位置处于正时区
*
* First coefficient is position (in pixels), second is velocity (in pixels per second),
* third is acceleration (in pixels per second squared).
* 第一个系数是位置(以像素为单位)
* 第二是速度(以像素/秒为单位)
* 第三是加速度(单位是像素/秒的平方)
*
* @hide For internal use only. Not a final API.
*/
public static final class Estimator {
// Must match VelocityTracker::Estimator::MAX_DEGREE
private static final int MAX_DEGREE = 4;
/**
* Polynomial coefficients describing motion in X.
* 描述X中运动的多项式系数
*/
public final float[] xCoeff = new float[MAX_DEGREE + 1];
/**
* Polynomial coefficients describing motion in Y.
* 描述Y中运动的多项式系数
*/
public final float[] yCoeff = new float[MAX_DEGREE + 1];
/**
* Polynomial degree, or zero if only position information is available.
* 多项式次,或零,如果只提供位置信息
*/
public int degree;
/**
* Confidence (coefficient of determination), between 0 (no fit) and 1 (perfect fit).
* 判定系数 0 - 1 (不吻合 和 全吻合)
*/
public float confidence;
/**
* Gets an estimate of the X position of the pointer at the specified time point.
* 获取指针在指定时间点处的X位置的估计值
* @param time The time point in seconds, 0 is the last recorded time.
* 时间点以秒为单位,0是最后记录的时间
* @return The estimated X coordinate.估计的X坐标
*/
public float estimateX(float time) {
return estimate(time, xCoeff);
}
/**
* Gets an estimate of the Y position of the pointer at the specified time point.
* @param time The time point in seconds, 0 is the last recorded time.
* @return The estimated Y coordinate.
*/
public float estimateY(float time) {
return estimate(time, yCoeff);
}
/**
* Gets the X coefficient with the specified index.
* 获取具有指定索引的X系数
* @param index The index of the coefficient to return.
* 返回index 的 系数
* @return The X coefficient, or 0 if the index is greater than the degree.
* X系数,如果index大于度,则为0
*/
public float getXCoeff(int index) {
return index <= degree ? xCoeff[index] : 0;
}
/**
* Gets the Y coefficient with the specified index.
* @param index The index of the coefficient to return.
* @return The Y coefficient, or 0 if the index is greater than the degree.
*/
public float getYCoeff(int index) {
return index <= degree ? yCoeff[index] : 0;
}
//估计值的算法
private float estimate(float time, float[] c) {
float a = 0;
float scale = 1;
for (int i = 0; i <= degree; i++) {
a += c[i] * scale;
scale *= time;
}
return a;
}
}
}