我正在尝试覆盖UITableView(实际上是UIScrollView子类)中的默认行为。基本上,我的表占据了屏幕的三分之一,我希望能够将项目从表格拖动到屏幕的其余部分 - 通过按住然后拖动,以及垂直拖动到表格。我能够使用默认的UIScrollView touchesShouldBegin / touchesShouldCancel和touchesBegan / Moved / Ended-Cancelled来实现第一种技术,但第二种技术给我带来了一些麻烦。
我的问题是:我希望能够检测到拖动,但我还希望能够在不拖动时滚动。为了做到这一点,我必须执行我的拖动检测,直到并包括调用touchesShouldCancel时的点。 (这是因为touchesShouldCancel是UIScrollView决定是否继续将触摸传递给其子视图或滚动的分支点。)不幸的是,UIScrollView的取消半径相当小,如果用户触摸一个单元格然后真的移动他们的手指很快,只接触到了开关。 (如果用户移动缓慢,我们通常会在调用touchesShouldCancel之前获得一些touchesMoved。)因此,我无法计算触摸方向,因为我只有touchesBegan中的一个点。
如果我可以在任何特定时刻查询触摸而不必依赖触摸回调,我可以很容易地解决这个问题,但据我所知,我不能这样做。如果我可以自行决定取消滚动视图(并随后调用touchesShouldCancel),或至少延迟调用touchesShouldCancel,也可以修复问题,但我也不能这样做。
相反,我一直试图通过UITableView在单独的叠加视图中捕获几个touchesBegan / Moved调用(最多2个或3个),然后将我的触摸转发到表。这样,我的表保证在调用touchesShouldCancel时已知道拖动方向。您可以在此处阅读有关此方法的变体:
(是的,他们做的事情有点不同,但我认为关键是在预处理完成后将触摸转发给UITableView。)
不幸的是,这似乎不起作用。使用touchesBegan / Moved / Ended-Cancelled调用我的表视图不会移动表,也不会将它们转发到表的hitTest视图(我的测试是表本身或表格单元)。更重要的是,我检查了单元格的nextResponder是什么,结果是表格,所以这也不起作用。根据我的理解,这是因为UIScrollView在近期的某个时刻切换到使用手势识别器来执行其重要的拖动/滚动检测,据我所知,你不能像通常的手势识别器那样转发触摸参与其中。
这是另一回事:即使手势识别器在3.2中正式发布,它们仍然在3.1.3中,尽管你不能使用API。我认为UIScrollView已经在3.1.3中使用它们了。
呼!所以这是我的问题:
谢谢!
答案 0 :(得分:0)
好的,我终于找到了问题的答案。实际上有两个答案。
Convoluted解决方案:子类UIWindow并覆盖sendEvent以存储最后一个触摸的位置。 (重写sendEvent是“事件处理指南”中给出的示例之一。)然后,Scroll View可以在调用touchesShouldCancel时查询窗口以获取最后一次触摸。
更简单的解决方案:不久之后,我注意到Facebook的Three20库存储UITouches而不保留它们。我一直认为你不应该将UITouch对象保留在本地范围之外,但Apple的文档只明确禁止保留。 (“UITouch对象在多点触控序列中是持久的。在处理事件时,不应该保留UITouch对象。如果需要保持从一个阶段到另一个阶段的触摸信息,您应该从UITouch对象复制该信息。“)因此,简单地将初始UITouch存储在表中并在调用touchesShouldCancel时查询其新位置可能是合法的。
不幸的是,在最坏的情况下,这两种技术都只给我2个采样点,这不是一个非常准确的方向测量。如果我可以简单地延迟表的触摸处理或手动调用touchesShouldCancel会好得多,但据我所知,要么是非常hacky或完全不可能/非法这样做。