Android ACTION_MOVE阈值

时间:2011-07-22 02:27:43

标签: android touch move ontouchlistener threshold

我正在编写一个应用程序,包括用手指在屏幕上书写,或最终用手写笔。我有那个部分在工作。在ACTION_DOWN上,开始绘图;在ACTION_MOVE上,添加线段;在ACTION_UP上,完成一行。

问题是在ACTION_DOWN之后,显然指针需要移动距离它开始的位置超过10个像素(基本上是起点周围的20x20框)才能开始发送ACTION_MOVE事件。离开盒子后,移动事件都非常准确。 (我通过测试得出10像素的东西。)因为这是用于书写或绘图,10像素是一个相当大的损失:取决于你试图写的小,你可能会失去第一个字母或两个。我一直无法找到任何相关内容 - 只有一两个论坛上的帖子,比如http://android.modaco.com/topic/339694-touch-input-problem-not-detecting-very-small-movements/page_pid_1701028#entry1701028。它似乎出现在某些设备或系统上,而不是其他设备或系统上。但是,当你拥有它时,没有关于如何摆脱它的想法。

我正在使用带有Android 3.1的Galaxy Tab 10.1。我已经尝试了几种不同的东西来试图摆脱它:我已经尝试将事件的坐标设置为其他东西,看看我是否可以欺骗它以为光标位于不同的位置;我尝试用更改的坐标重新调度事件(我的处理程序对新点做出反应,但仍然没有响应10像素半径的移动。)我在源代码中搜索了对该效果的任何引用,并且没有找到(虽然我认为它来自不同版本的Android - 3.1的代码尚未发布,是吗?)我已经搜索了查询指针当前状态的方法,所以我可以只有一个计时器捕获更改,直到指针超过阈值。没有相应的移动事件,找不到任何获得指针坐标的方法。没有任何效果。有没有人知道这件事,或有任何想法或解决方法?谢谢。

- 更新:拖放事件显示相同的阈值。

3 个答案:

答案 0 :(得分:23)

我同意@passsy的帖子,但得出了不同的结论。首先如上所述,mTouchSlop是我们感兴趣的值,并通过ViewConfiguration.get(context).getScaledTouchSlop();

公开

如果您检查ViewConfiguraton的Android来源, TOUCH_SLOP 的默认值为 8dip ,但评论中提到此值仅为后备,并且在构建该特定设备的Android OS时定义实际值。 (它可能大于或小于此值。它似乎适用于Galaxy Tab设备)

更具体的代码示例,mTouchSlop初始化ViewConfiguration时会从View读取onTouchEvent值,但只能在View方法中访问该值。如果您展开super并覆盖此方法(不调用mTouchSlop),那么View类中getTouchSlop的行为将不再相关。

更多说明(对我们而言)当将Android设置更改为覆盖屏幕上的触摸事件时,使用小拖动的触摸不会注册为动作事件,而是来自Android操作系统的十字准线的事实突出显示不动。由此我们的结论是,最小拖动距离在操作系统级别实施,您的应用程序将永远不会知道小于 TOUCH_SLOP 值的拖动事件。您还应该知道 TOUCH_SLOP 不应该直接使用,并且API会弃用getScaledTouchSlop方法,并建议考虑设备屏幕大小和像素密度的{{1}}。这样的副作用是在不同设备上感知的实际最小行程长度可以变化。例如,在Galaxy Tab 2.0 7.0上“感觉我们能够使用与在Galaxy Tab 2.0 10.1上运行时相同的代码库来绘制更短的最小笔画”

您还应该知道(如果您找到改变此值的方法),此值将确定Android系统如何区分点击和笔划。也就是说,如果您点击屏幕但手指在执行点击时略微移动,如果它移动的次数小于 TOUCH_SLOP ,则会被解释为点击,但如果移动的次数超过,则会被解释为中风TOUCH_SLOP 即可。因此,将 TOUCH_SLOP 设置为较小的值会增加将点击解释为笔划的几率。

我们自己的结论是,这个最小距离不是可以在实践中改变的东西,而是我们需要忍受的东西。

答案 1 :(得分:4)

问题出在课程视图https://github.com/android/platform_frameworks_base/blob/master/core/java/android/view/View.java

上的第6549行
if (!pointInView(x, y, mTouchSlop)) {...}

 /**
 * Utility method to determine whether the given point, in local coordinates,
 * is inside the view, where the area of the view is expanded by the slop factor.
 * This method is called while processing touch-move events to determine if the event
 * is still within the view.
 */
private boolean pointInView(float localX, float localY, float slop) {
    return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
            localY < ((mBottom - mTop) + slop);
}

mTouchSlop在构造函数中设置

mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();

您可以扩展View并将mTouchSlop设置为零。我没有看到另一种设置mTouchSlop的方法。没有getApplicationContext.setScaledTouchSlop(int n)等功能。

答案 2 :(得分:1)

扩展视图类。

在没有“ @Override”注释的情况下覆盖pointInView方法并设置touchSlop = 0:

public boolean pointInView(float localX, float localY, float slop) {
    slop = 0;
    return localX >= -slop && localY >= -slop && localX < (getWidth() + slop) &&
            localY < (getBottom() + slop);
}