【问题标题】:How to detect someone tapping outside of a UIImageView如何检测有人在 UIImageView 之外点击
【发布时间】:2025-12-04 16:00:01
【问题描述】:

我有一个作为子视图添加的 UIImageView。它会在按下按钮时显示。

当有人在应用程序的任何部分中的 UIImageView 之外点击时,我希望 UIImageView 消失。

@interface SomeMasterViewController : UITableViewController <clip>

<clip>

@property (strong, nonatomic) UIImageView *someImageView;

* 和 Apple 的文档中有一些提示听起来像是我需要的。

但是,我想在这里检查一下我的方法。我的理解是代码需要

  1. 注册一个 UITapGestureRecognizer 以获取应用程序中可能发生的所有触摸事件

  2. UITapGestureRecognizer 应该有它的 cancelsTouchesInView 和 delaysTouchesBegan 和 delaysTouchesEnded 设置为 NO。

  3. 将这些触摸事件与 someImageView 进行比较(如何?使用 UIView hitTest:withEvent?)

更新:我正在向主 UIWindow 注册一个 UITapGestureRecognizer。

最终未解决的部分

我有一个 UITapGestureRecognizer 将调用的 handleTap:(UITapGestureRecognizer *)。如何获取给定的 UITapGestureRecognizer 并查看点击是否落在 UIImageView 之外?识别器的 locationInView 看起来很有希望,但我没有得到我期望的结果。我希望在单击某个 UIImageView 时看到它,而在单击另一个位置时看不到 UIImageView。我感觉 locationInView 方法使用错误。

这是我对 locationInView 方法的调用:

- (void)handleTap:(UITapGestureRecognizer *)gestureRecognizer
{
    if (gestureRecognizer.state != UIGestureRecognizerStateEnded) {
        NSLog(@"handleTap NOT given UIGestureRecognizerStateEnded so nothing more to do");
        return;        
    }

    UIWindow *mainWindow = [[[UIApplication sharedApplication] delegate] window];
    CGPoint point = [gestureRecognizer locationInView:mainWindow];
    NSLog(@"point x,y computed as the location in a given view is %f %f", point.x, point.y);

    UIView *touchedView = [mainWindow hitTest:point withEvent:nil];
    NSLog(@"touchedView = %@", touchedView); 
}

我得到以下输出:

<clip>point x,y computed as the location in a given view is 0.000000 0.000000

<clip>touchedView = <UIWindow: 0x8c4e530; frame = (0 0; 768 1024); opaque = NO; autoresize = RM+BM; layer = <UIWindowLayer: 0x8c4c940>>

【问题讨论】:

    标签: ios uigesturerecognizer uitouch


    【解决方案1】:

    认为你可以说[event touchesForView:&lt;image view&gt;]。如果返回一个空数组,则关闭图像视图。在表格视图控制器的touchesBegan:withEvent: 中执行此操作,并确保调用[super touchesBegan:touches withEvent:event] 否则您的表格视图将完全停止工作。你可能甚至不需要实现touchesEnded:/Cancelled:...touchesMoved:...

    在这种情况下,UITapGestureRecognizer 绝对看起来有点矫枉过正。

    【讨论】:

    • 谢谢!顺便说一句,你的意思是 touchesBegan:withEvent 而不是 "touchesBegan:touches forEvent:event" 对还是我错过了什么? :)
    • 我喜欢这个建议。但是,在 UITableViewController 中没有调用 touchesBegan:withEvent。我想我遇到了*.com/questions/6286230/…
    • 是的,你是对的。两次。不知道如何解决这个问题,我会尝试一下并回复您。如果你弄明白了,请告诉我们!
    • (另外,你应该看看this post about UIImageView overlays。我认为,如果你希望图像高于表格视图,你绝对应该考虑其中的方法,它使用一个新的 UIWindow。在这种情况下,您可能还必须继承 UIImageView 以捕捉触摸...)
    • 另一个问题产生了一个稍微不同的简单想法:*.com/questions/10067059/…"create a UIWindow subclass"
    【解决方案2】:

    您可以使用触摸功能来做到这一点:

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

    当用户首先触摸屏幕时,您的 touchBegan 函数会被调用。

    联系开始:

     -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
    
        CGPoint pt = [[touches anyObject] locationInView:self]; 
    }
    

    所以你有用户触摸的点。那么你必须找到该点是否在你的 UIImageView 中。

    但是如果你可以给你的 UIImageViews 标签。这将非常容易。

    -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    
          UITouch *touch = [touches anyObject ];
    
          if( yourImageView.tag==[touch view].tag){
    
             [[self.view viewWithTag:yourImageView.tag] removeFromSuperView];
             [yourImageView release];
    
          }
    }
    

    【讨论】: