我正在尝试找到一种方法来计算手势期间行进的距离。我可以使用 MotionEvent.ACTION_DOWN 和 MotionEvent.ACTION_UP 或 MotionEvent.ACTION_MOVE 获得两点之间的距离。但这并不能说明进入一个圈子。它会计算 0,因为您一直向后移动。我正在寻找总行驶距离,最好以像素为单位,以便在需要时进一步操作它。
3 回答
您可以使用MotionEvent的历史资料。根据 API Doc 的示例,您可以这样做(为简单起见,我的示例不涉及多点触控):
在 ACTION_MOVE 和 ACTION_UP 上执行此操作,其中startX
,startY
将是最后一个已知坐标,例如来自最后一个 ACTION_DOWN 事件。
float getDistance(float startX, float startY, MotionEvent ev) {
float distanceSum = 0;
final int historySize = ev.getHistorySize();
for (int h = 0; h < historySize; h++) {
// historical point
float hx = ev.getHistoricalX(0, h);
float hy = ev.getHistoricalY(0, h);
// distance between startX,startY and historical point
float dx = (hx - startX);
float dy = (hy - startY);
distanceSum += Math.sqrt(dx * dx + dy * dy);
// make historical point the start point for next loop iteration
startX = hx;
startY = hy;
}
// add distance from last historical point to event's point
float dx = (ev.getX(0) - startX);
float dy = (ev.getY(0) - startY);
distanceSum += Math.sqrt(dx * dx + dy * dy);
return distanceSum;
}
一阶近似值是对检测到的每一个微小运动的局部长度求和:
上ACTION_DOWN
total = 0;
xPrec = ev.getX();
yPrec = ev.getY();
上ACTION_MOVE
final float dx = ev.getX() - xPrec;
final float dy = ev.getY() - yPrec;
final float dl = sqrt(dx * dx + dy * dy);
total += dl;
xPrec = ev.getX();
yPrec = ev.getY();
在ACTION_UP
你可以做任何你想做的事情,total
其中包含你的路径的总近似长度。
如果您阅读有关MotionEvent
http://developer.android.com/reference/android/view/MotionEvent.html的官方文档,您将看到名为Batching的部分,它解释了一个给定的运动事件可以将多个运动样本批处理在一起。为了获得最佳的一阶近似值,您需要使用
getHistorySize
, getHistoricalX
,来消耗所有这些样本getHistoricalY
。不要忘记处理位于getX
和中的最新样本getY
。
如果您需要更好的近似值,我建议您阅读有关曲线拟合问题http://en.wikipedia.org/wiki/Curve_fitting,但由于触摸事件的频率非常快,您可能不需要这样做并获得满足一阶近似。
我不知道这是否是最好的方法,但是您可以在每次 MotionEvent.ACTION_MOVE 触发到数组时捕获数据点,然后在完成手势后计算从点到点的累积距离……到点。