【问题标题】:How to cancel a sequence of UITouch events?如何取消一系列 UITouch 事件?
【发布时间】:2010-10-06 17:20:35
【问题描述】:

我有一个响应触摸事件的UIImage 视图。如果触摸超出特定范围,我想取消触摸序列,即进一步调用touchesMoved:。我该怎么做?

我知道在touchesMoved: 我可以检查触摸对象的坐标并忽略它,但我不知道如何完全取消序列。我没有看到 Apple Developer UIResponder Reference 中记录的任何方法,我可以调用它来取消触摸序列。

【问题讨论】:

  • 你能解决这个问题吗?

标签: iphone ios uitouch touchesmoved uiresponder


【解决方案1】:

此解决方案可能有点笨拙,但您可以实现并手动调用

- (void) touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;

我将这个解决方案松散地基于我对 Apple 的 iPhone sample code 站点上的 MoveMe 示例应用程序所做的一些调整,在该站点我修改了 touchesMoved 方法,如下所示:

- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
     UITouch *touch = [touches anyObject];
     if ([touch view] == placardView)
         CGPoint location = [touch locationInView:self];
         placardView.center = location;
         // I added the following line:
         [self touchesCancelled:touches withEvent:event];
         return;
}

【讨论】:

  • 谢谢,等我回到我的 Mac 上试试。但这会取消后续的触摸事件吗?在我看来,在手动调用 touchesCancelled 之后,系统仍然会调用 touchesMoved。
  • 在 MoveMe 示例代码的范围内,它将取消触摸,但我相信你是对的,仍然会调用 touchesMoved。我越想越觉得 touchesCancelled 是正确的选择。
  • 这行不通,“移动”事件不断发生。
【解决方案2】:

尝试将 UIImageView 的 userInteractionEnabled 属性临时设置为 NO

【讨论】:

    【解决方案3】:

    您需要调用[super touchesMoved:withEvent:] 以便让超级视图从事件中清除,但更重要的是,您需要调用[super touchesCancelled:withEvent:]

    当我检测到滑动时,我在单元格上使用了以下内容以防止它被选中:

    - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
    {
        if (!showingEdit) {
            if (IS_FAR_ENOUGH_TO_BE_A_SWIPE) {
                RESPOND_TO_SWIPE
                showingEdit = YES;
                [super touchesCancelled:touches withEvent:event];
            } else {
                [super touchesMoved:touches withEvent:event];
            }
        }
    }
    
    - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
    {
        if (!showingEdit) {
            [super touchesEnded:touches withEvent:event];
        }
    }
    

    【讨论】:

      【解决方案4】:

      我最近遇到了同样的问题,并找到了解决它的标准方法。 您可以使用 [[UIApplication sharedApplication] beginIgnoringInteractionEvents] 停止向整个应用程序传递 touchesMoved 事件。当您需要再次接收触摸时,请确保使用 [[UIApplication sharedApplication] endIgnoringInteractionEvents] 启用它们。

      【讨论】:

        【解决方案5】:

        我认为这不可能,因为我没有看到它记录在案,而且这些解决方案都不起作用。

        【讨论】:

          【解决方案6】:

          “蛮力”解决方案取决于它是否适合您的需求:删除并重新初始化接收触摸或响应它们的子视图(当然要注意框架和内容)。

          【讨论】:

            【解决方案7】:

            此代码将为您提供帮助。我在touchesMoved: 方法中禁用了触摸事件,我在touchesCancelled: 方法中启用了触摸事件

            -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
            {
                 UITouch *touch = [touches anyObject];
                 .......
                 .......
                 Your code
                 .......
                 .......
            
                 //Condition when you want to disable touch event
            
                 [[UIApplication sharedApplication] beginIgnoringInteractionEvents];
            
                 .......
                 .......
                 Your code
                 .......
                 .......
             }
            
            
            - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
            {
                [[UIApplication sharedApplication] endIgnoringInteractionEvents];
            }
            

            【讨论】:

              【解决方案8】:

              我通过从父视图中删除视图并直接添加回来来实现这一点。

              [view retain];
              UIView *sv = view.superview;
              [view removeFromSuperview];
              [sv addSubview:view];
              [view release];
              

              这会破坏视图的响应者链,因此视图不会接收到任何剩余的触摸。下一次触摸仍会正常接收。

              【讨论】:

                【解决方案9】:

                在 iOS5 上,UITouch 中似乎有一个私有方法

                -(void)setSentTouchesEnded:(BOOL)ended;
                

                根据苹果的实现,它可能会停止发送事件

                另一种方法是使用关联对象

                - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
                {
                    if ([(NSNumber *)objc_getAssociatedObject(touch, &outKey) boolValue])
                        return;
                    if (sometouchisoutsideofview) {
                        objc_setAssociatedObject(touch, &outKey, [NSNumber numberWithBool:YES], OBJC_ASSOCIATION_RETAIN);
                    }
                }
                

                【讨论】:

                  【解决方案10】:

                  我只是想解决这样的问题,发现她列出的所有解决方案都不适合我。我能做到的最好的办法是暂时忽略触摸,但是当触摸重新进入视图时它们又恢复了。

                  终于解决了。

                  1. 设置一个名为“已禁用”的布尔标志
                  2. 在touchedMoved 中,首先检查触摸是否在所需视图内。如果不是,请将 disabled 标志设置为 YES。
                  3. 仍在touchedMoved 中,在执行您的操作之前检查标志。 所以,在这一点上,如果他们在视野之外,什么都不会发生。
                  4. 在 touchesEnded 中,将禁用标志设置为 NO。因此,触摸序列实际上会暂停,直到用户抬起手指为止。

                  我想这对你有用,除非你有具体的理由需要取消触摸序列。

                  【讨论】:

                  • 您甚至可以使用单个标志进行 UIControl 样式的跟踪。这感觉比一次取消整个事件序列更自然。
                  【解决方案11】:

                  您可以为 UITouch 创建类别。你可以声明

                  @property (nonatomic,strong,readwrite) UIView *view;
                  

                  例如,当你将 touch.view 更改为 nil 时,你可以模拟调度触摸事件的结束

                  【讨论】:

                    【解决方案12】:

                    您可以检查,触摸点位置是否在 CGRect 中(即点是否在您的图像视图的矩形中)。如果它们不在该 Rect 中,则触摸将被取消。

                    -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
                     {
                    UITouch *touch = [touches anyObject];
                    CGPoint touchLocation = [touch locationInView:self.view];
                    
                        if (CGRectContainsPoint(myImageView, touchLocation))
                        {
                           lastPoint = [touch locationInView: myImageView];
                        }
                    
                        NSLog(@"Last :%.2f - %.2f",lastPoint.x, lastPoint.y);   
                      }
                    
                     - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
                     {
                      CGPoint currentPoint;
                      UITouch *touch = [touches anyObject];
                      CGPoint touchLocation = [touch locationInView:self.view];
                    
                         if (CGRectContainsPoint(myImageView.frame, touchLocation))
                         {
                           currentPoint = [touch locationInView: myImageView];
                         }
                     }
                    

                    【讨论】:

                    • 该代码不会取消对touchesMoved: 的进一步调用。它只是忽略它们。
                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多