调整触摸到视图的传递

有时您希望某个视图在手势识别器之前接受触摸。但是,在可以将触摸的传递路径更改为视图之前,您需要了解默认行为。在简单情况下,当发生触摸时,触摸对象从UIApplication对象传递到UIWindow对象。然后,window首先将任何手势识别器发送到触摸发生位置的视图(或视图的父视图),然后将触摸传递给视图对象本身。

图1-5 触摸事件的默认传递路径

手势识别器获得首先识别触摸的机会

window延迟触摸对象(touch)到视图的传递,以便手势识别器可以首先分析触摸。在延迟期间,如果手势识别器识别出触摸手势,则该窗口永远不会将触摸对象递送到视图,并且还取消其先前发送到该视图的任何触摸对象,该视图是该识别序列的一部分。

例如,如果您有一个需要双指触摸的离散手势的手势识别器,则会转换为两个单独的触摸对象。触摸发生时,触摸对象从应用程序对象传递到发生触摸的视图的窗口对象,并发生以下顺序,如图1-6所示。

图1-6 触摸消息的顺序

  1. window通过touchesBegan:withEvent:方法将开始阶段的两个触摸对象发送给手势识别器。他的手势识别器尚未识别该手势,所以其状态是可能的(Possible)。窗口将这些相同的触摸发送到手势识别器所连接的视图。
  2. 该窗口(window)将Moved阶段的两个触摸对象(通过touchesMoved:withEvent:方法)发送到手势识别器。识别器仍然没有检测到手势,并且仍然处于可能状态。窗口然后将这些触摸发送到所附视图。
  3. 该窗口通过touchesEnded:withEvent:方法将Ended阶段中的一个触摸对象发送给手势识别器。此触摸对象不会为该手势提供足够的信息,但该窗口会从附加的视图中隐藏该对象。
  4. 窗口在Ended阶段发送其他触摸对象。手势识别器现在识别其手势,因此将其状态设置为识别。在发送第一个动作消息之前,视图调用touchesCancelled:withEvent:方法来使以前在“开始”和“移动”阶段中发送的触摸对象失效。Ended阶段的触摸被取消。

现在假定最后一步中的手势识别器决定它正在分析的这个多点触摸顺序不是它的手势。它将其状态设置为UIGestureRecognizerState失败。然后,窗口将Endded阶段中的两个触摸对象发送到touchesEnded:withEvent:消息中的附加视图。

连续手势的手势识别器遵循相似的顺序,除了在触摸对象达到Ended阶段之前它更有可能识别其手势之外。在识别它的手势后,它将其状态设置为UIGestureRecognizerStateBegan(未识别)。该窗口将多点触控序列中的所有后续触摸对象发送至手势识别器,但不发送至附加视图。

影响触摸到视图的传递

您可以更改多个UIGestureRecognizer属性的值,以某种方式更改默认传递路径。如果您更改这些属性的默认值,则会在行为中获得以下差异:

  • delaysTouchesBegan(默认为NO) - 正常情况下,窗口将开始和移动阶段中的触摸对象发送到视图和手势识别器。将延迟触发设置为YES可防止窗口将开始阶段的触摸对象传送到视图。这确保了当手势识别器识别其手势时,触摸事件的任何部分都不会被传递到所附视图。设置此属性时请谨慎,因为它可能会使界面无法响应。 此设置提供了与UIScrollView上的delaysContentTouches属性类似的行为;在这种情况下,当触摸开始后很快开始滚动时,滚动视图对象的子视图永远不会接收到触摸,所以没有视觉反馈闪光。
  • delaysTouchesEnded(默认为YES) - 当此属性设置为YES时,它确保视图不会完成手势可能稍后要取消的操作。当手势识别器正在分析触摸事件时,窗口不会将已结束阶段的触摸对象传送到已附加视图。如果手势识别器识别其手势,则触摸对象被取消。 如果手势识别器未识别其手势,则窗口通过touchesEnded:withEvent:消息将这些对象传递给视图。将此属性设置为NO允许视图与手势识别器同时分析Ended阶段中的触摸对象。 例如,考虑一个视图具有需要两次敲击的轻击手势识别器,并且用户双击该视图。将该属性设置为YES,该视图将获取touchesBegan:withEvent:,touchesBegan:withEvent :, touchesCancelled:withEvent :, touchesCancelled:withEvent :.如果此属性设置为NO,则视图将获得以下消息序列:touchesBegan:withEvent:,touchesEnded:withEvent :, touchesBegan:withEvent :, touchesCancelled:withEvent :,这意味着在touchesBegan:withEvent:中,视图可以 识别双击。

如果手势识别器检测到它确定的触摸不是其手势的一部分,则它可以将触摸直接传递到其视图。为此,手势识别器调用ignoreTouch:forEvent:自身,传入触摸对象。

results matching ""

    No results matching ""