Android ACTION_MOVE阈值
我正在编写一个应用程序,需要使用手指或最终使用手写笔在屏幕上书写。我有那部分工作。在 ACTION_DOWN 时,开始绘制;在 ACTION_MOVE 上,添加线段;在 ACTION_UP 上,完成该行。
问题是,在 ACTION_DOWN 之后,显然指针需要从其开始位置移动超过 10 个像素(基本上是起点周围的 20x20 框)才能开始发送 ACTION_MOVE 事件。离开盒子后,移动事件都相当准确。 (我通过测试发现了 10 像素的问题。)由于这意味着用于书写或绘图,因此 10 像素是一个相当大的损失:根据您要写的小值,您可能会丢失第一个字母或两个。我找不到任何相关信息 - 只有一两个论坛上的几篇帖子,例如 ht tp://android.modaco.com/topic/339694-touch-input-problem-not-detecting-very-small-movements/page_pid_1701028#entry1701028。它似乎存在于某些设备或系统上,而不存在于其他设备或系统上。不过,当你拥有它时,不知道如何摆脱它。
我使用的是 Galaxy Tab 10.1,运行 Android 3.1。我尝试了几种不同的方法来尝试摆脱它:我尝试将事件的坐标设置为其他值,看看是否可以欺骗它认为光标位于不同的位置;我尝试在坐标发生变化的情况下重新调度事件(我的处理程序对新点做出了反应,但仍然没有对 10 像素半径内的移动做出响应。)我已经在源代码中搜索了对该效果的任何引用,并没有找到(虽然我认为它来自不同版本的 Android - 3.1 的代码尚未发布,是吗?)我已经搜索了查询指针当前状态的方法,所以我可以有一个计时器抓住更改直到指针越过阈值。如果没有相应的移动事件,则找不到任何获取指针坐标的方法。什么都没起作用。有谁知道这件事,或者有任何想法或解决方法?谢谢。
-- 更新:拖放事件显示相同的阈值。
I'm writing an app that involves writing on the screen using one's finger, or eventually a stylus. I have that part working. On ACTION_DOWN, starts drawing; on ACTION_MOVE, adds line segments; on ACTION_UP, finishes line.
The problem is that after ACTION_DOWN, apparently the pointer needs to move more than 10 pixels away from where it started (basically a 20x20 box around the starting point) in order to begin sending ACTION_MOVE events. After leaving the box, the move events are all quite accurate. (I figured out the 10 pixel thing by testing it.) Since this is meant to be used for writing or drawing, 10 pixels is a fairly significant loss: depending on how small you're trying to write, you can lose the first letter or two. I haven't been able to find anything about it - only a couple posts on a forum or two, like http://android.modaco.com/topic/339694-touch-input-problem-not-detecting-very-small-movements/page_pid_1701028#entry1701028. It seems to be present on some devices or systems and not others. No ideas as to how to get rid of it when you have it, though.
I'm using a Galaxy Tab 10.1, with Android 3.1. I've tried several different things to try to get rid of it: I've tried setting the event's coords to something else to see if I could trick it into thinking the cursor was in a different place; I tried re-dispatching the event with the coords changed (my handler reacted to the new points, but still didn't respond to movements in the 10-pixel radius.) I've searched through source code for any references to the effect, and found none (though I think it's from a different version of Android - code for 3.1 isn't released yet, is it?) I've searched for methods of querying the current state of the pointers, so I could just have a timer catch the changes until the pointer crossed the threshold. Couldn't find any way of getting pointer coords without a corresponding movement event. Nothing worked. Does anybody know anything about this, or have any ideas or work-arounds? Thank you.
-- Update: Drag and drop events show the same threshold.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我部分同意@passsy 的帖子,但得出了不同的结论。首先如前所述,
mTouchSlop
是我们感兴趣的值,并通过ViewConfiguration.get(context).getScaledTouchSlop();
公开,如果您检查 Android 源代码ViewConfiguraton,默认值TOUCH_SLOP 是 8dip,但评论提到该值只是后备值,实际值是在构建该特定设备的 Android 操作系统时定义的。 (它可能大于或小于此值。它似乎适用于 Galaxy Tab 设备)
更具体到代码示例,
mTouchSlop
值是从ViewConfiguration
当View
初始化时,但该值只能在onTouchEvent
方法中访问。如果您扩展View
并重写此方法(不调用super
),则View
类中mTouchSlop
的行为不再相关。(对我们来说)更能说明问题的是,当更改 Android 设置以在屏幕上覆盖触摸事件时,小幅拖动的触摸不会注册为运动事件,这一点通过 Android 操作系统中的十字准线不移动这一事实突出显示。由此我们得出的结论是,最小拖动距离是在操作系统级别强制执行的,并且您的应用程序永远不会意识到小于TOUCH_SLOP值的拖动事件。您还应该注意,不应直接使用 TOUCH_SLOP,并且该 API 已弃用
getTouchSlop
方法,并建议使用getScaledTouchSlop
,该方法采用设备屏幕尺寸和考虑像素密度。这样做的副作用是,在不同设备上感知的实际最小行程长度可能会有所不同。例如,在 Galaxy Tab 2.0 7.0" 上,感觉我们能够使用与在 Galaxy Tab 2.0 10.1" 上运行时相同的代码库绘制更短的最小笔划。您还应该意识到(如果您找到一种方法来更改此值) ),该值决定了Android系统如何区分点击和笔画。也就是说,如果您点击屏幕,但手指在执行点击时轻微移动,如果移动距离小于 TOUCH_SLOP,则会被解释为点击,但如果移动距离超过 ,则会被解释为划动。 TOUCH_SLOP。因此,将 TOUCH_SLOP 设置为较小的值将增加将轻击解释为笔划的可能性。
我们自己的结论是,这个最小距离在实践中是无法改变的,是我们需要忍受的。
I agree in part with the post by @passsy but come to a different conclusion. Firstly as mentioned, the
mTouchSlop
is the value that we are interested in and is exposed viaViewConfiguration.get(context).getScaledTouchSlop();
If you check the Android source for the ViewConfiguraton, the default value for TOUCH_SLOP is 8dip, but the comments mention that this value is a fallback only, and the actual value is defined when the Android OS for that specific device is built. (it may be more or less than this value. It appears to hold true for the Galaxy Tab devices)
More specific to the code sample, the
mTouchSlop
value is read from theViewConfiguration
when theView
is initialised, but the value is only accessed in theonTouchEvent
method. If you extendView
and override this method (without callingsuper
) then the behaviour ofmTouchSlop
in theView
class is no longer relevant.More telling (to us) was that when changing the Android settings to overlay touch events on the screen, a touch with a small drag does not register as a motion event, highlighted by the fact that the crosshairs from the Android OS do not move. From this our conclusion is that the minimal drag distance is being enforced at the OS level and your application will never be aware of drag events smaller than the TOUCH_SLOP value. You should also be aware that TOUCH_SLOP should not be used directly and the API deprecates the
getTouchSlop
method and recommendsgetScaledTouchSlop
which takes the device screen size and pixel density into account. A side effect of this is that the actual minimum stroke length as perceived on different devices may vary. eg on a Galaxy Tab 2.0 7.0" it feels like we are able to draw shorter minimum strokes using the same code base than when running on a Galaxy Tab 2.0 10.1"You should also be aware that (if you find a way to alter this value), this value determines how Android systems distinguish between taps and strokes. That is if you tap the screen but your finger moves slightly while performing the tap, it will be interpreted as a tap if it moved less than TOUCH_SLOP, but as a stroke if it moved more than TOUCH_SLOP. Therefore setting TOUCH_SLOP to a smaller value will increase the chance that a tap will be interpreted as a stroke.
Our own conclusion is that this minimum distance is not something that can be changed in practice and is something we need to live with.
问题出在类 View https 中的第 6549 行: //github.com/android/platform_frameworks_base/blob/master/core/java/android/view/View.java
mTouchSlop 在构造函数中设置
您可以扩展 View 并将 mTouchSlop 设置为零。我没有看到其他设置 mTouchSlop 的方法。没有像
getApplicationContext.setScaledTouchSlop(int n)
这样的函数。The problem is on Line 6549 in class View https://github.com/android/platform_frameworks_base/blob/master/core/java/android/view/View.java
mTouchSlop is set in the constructor
You can extend View and set mTouchSlop to zero. I don't see an other way to set mTouchSlop. There is no function like
getApplicationContext.setScaledTouchSlop(int n)
.扩展视图类。
重写不带“@Override”注释的 pointInView 方法并设置 touchSlop = 0:
Extend View Class.
Override pointInView method without "@Override" annotaion and set touchSlop = 0: