【问题标题】:How can I detect the touch event of an UIImageView?如何检测 UIImageView 的触摸事件?
【发布时间】:2010-10-25 16:49:52
【问题描述】:

我在导航栏上放置了一个图像(UIImageView)。现在我想检测触摸事件并处理该事件。我该怎么做?

【问题讨论】:

标签: ios iphone uiimageview uitouch


【解决方案1】:

实际上,不要那样做。

而是在 UIImageView 上添加一个具有自定义样式的按钮(除非您指定图像,否则没有按钮图形)。然后附加任何你想调用的方法。

您可以在许多情况下使用该技术,因为您确实希望屏幕的某些区域充当按钮,而不是弄乱 Touch 的东西。

【讨论】:

  • 我在导航栏添加了一个按钮,也可以处理触摸事件。但是,我想在这个按钮上添加一个圆形图像。你能告诉我如何以编程方式做到这一点吗?另外,您能否告诉我如何以编程方式将按钮属性设置为“自定义”?
  • 查看 UIButton 的文档 - 您需要为控件状态设置背景图像,您需要不同的图像用于正常与选定/突出显示。我相信按钮样式是您设置为 UIButtonStyleCustom 的样式 - 再次查看文档以了解 UIButton 上的样式属性。
  • 在 UIImageView 顶部添加一个 UIButton 是不是有点过头了?您正在添加一个额外的对象,而您可以只实现现有 UIImageView 对象的 touches 方法。没有?
  • 如果您查看内存中 UIButton 的大小,它实际上没什么,每个屏幕只有几个。您免费获得的是针对不同状态的整个目标动作接线(例如内部修饰)以及良好的行为,例如当您按下但将手指滑到侧面时不会触发。基本上按钮是整个系统中制作最精细的对象之一,并且认为您将执行更好的自定义触摸代码是疯狂的。使用便宜且运行良好的,将自定义工作留给框架尚未为您处理的事情。
  • 如果您只需要触摸事件(通过 addTaget:action:forControlEvents:),您也可以覆盖 UIControl。它比具有图像和多个状态的 UIButton 便宜一些。此外,我使用预处理器条件将覆盖控件的背景颜色更改为粉红色,这样我就可以准确地看到它们的位置(并记住它们存在:-)。
【解决方案2】:

UIImageView 派生自 UIView,而 UIView 派生自 UIResponder,因此它已准备好处理触摸事件。您需要提供touchesBegantouchesMovedtouchesEnded 方法,如果用户点击图像,它们将被调用。如果您想要的只是一个点击事件,那么使用自定义按钮并将图像设置为按钮图像会更容易。但是,如果您想对点击、移动等进行更细粒度的控制,这就是您要走的路。

您还需要查看更多内容:

  • 覆盖canBecomeFirstResponder并返回YES表示视图可以成为触摸事件的焦点(默认为NO)。

  • userInteractionEnabled 属性设置为YES。 UIViews 的默认值为 YES,但 UIImageViews 的默认值为 NO,因此您必须明确打开它。

  • 如果您想响应多点触控事件(即捏合、缩放等),您需要将 multipleTouchEnabled 设置为 YES。

【讨论】:

  • 我试过了,但我没有收到 touchesBegan 事件……这是为什么呢?
  • @Markus:我遇到了同样的问题,但通过在我的父视图上将 userInteractionEnabled 设置为 YES 来解决它。见stackoverflow.com/questions/5887305/…
【解决方案3】:

要向 UIImageView 添加触摸事件,请在 .m 文件中使用以下内容:

UITapGestureRecognizer *newTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(myTapMethod)];

[myImageView setUserInteractionEnabled:YES];

[myImageView addGestureRecognizer:newTap];


-(void)myTapMethod{
    // Treat image tap
}

【讨论】:

  • userInteractionEnabled = true 是容易忘记的部分,谢谢。
【解决方案4】:

您还可以添加 UIGestureRecognizer。它不需要您在视图层次结构中添加额外的元素,但仍然为您提供了所有编写精美的代码,用于通过相当简单的界面处理触摸事件:

    UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc]
                                            initWithTarget:self action:@selector(handleSwipe:)];
    swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
    [imgView_ addGestureRecognizer:swipeRight];        
    [swipeRight release];
    UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc]
                                            initWithTarget:self action:@selector(handleSwipe:)];
    swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
    [imgView_ addGestureRecognizer:swipeLeft];
    [swipeLeft release];

【讨论】:

  • 不要忘记为 imgView 设置 UserInteractionEnabled_
【解决方案5】:

在过去的几个小时里,我一直在不同的线程上试图为我的问题找到解决方案,但无济于事。我看到很多开发者都有这个问题,我想这里的人都知道这一点。我在UIScrollView 中有多个图像,试图在它们上获取点击事件。

我没有从UIImangeView 获得任何事件,但我确实从一个类似的UILable 获得了一个事件,我设置的参数非常相似。在 iOS 5.1 下。

我已经做了以下事情:

  1. 将 `UIImageView 和 parent 的 setUserInteractionEnabled 设置为 YES 查看。
  2. UIImageView 的 setMultipleTouchEnabled 设置为 YES。
  3. 尝试子类化UIImageView,没有任何帮助。

在下面附加一些代码,在这段代码中我初始化了UIImageViewUILabel,标签在触发事件方面工作正常。我尝试保留不相关的代码。

UIImageView *single_view = [[UIImageView alloc]initWithFrame:CGRectMake(200, 200, 100, 100)];
single_view.image = img;
single_view.layer.zPosition = 4;

UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapGestureCaptured:)];
[single_view addGestureRecognizer:singleTap];
[single_view setMultipleTouchEnabled:YES];
[single_view setUserInteractionEnabled:YES];
[self.myScrollView addSubview:single_view];
self.myScrollView.userInteractionEnabled = YES;

UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
testLabel.backgroundColor = [UIColor redColor];
[self.myScrollView addSubview:testLabel];
[testLabel addGestureRecognizer:singleTap];
[testLabel setMultipleTouchEnabled:YES];
[testLabel setUserInteractionEnabled:YES];
testLabel.layer.zPosition = 4;

以及处理事件的方法:

- (void)singleTapGestureCaptured:(UITapGestureRecognizer *)gesture
{
    UIView *tappedView = [gesture.view hitTest:[gesture locationInView:gesture.view] withEvent:nil];
    NSLog(@"Touch event on view: %@", [tappedView class]);
}

如前所述,标签点击被接收。

【讨论】:

    【解决方案6】:

    与其制作一个可触摸的 UIImageView 然后将其放置在导航栏上,不如只创建一个 UIBarButtonItem,它是由 UIImageView 制作的。

    首先制作图像视图:

    UIImageView *yourImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"nameOfYourImage.png"]];
    

    然后将 barbutton 项从图像视图中移出:

    UIBarButtonItem *yourBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:yourImageView];
    

    然后将栏按钮项添加到您的导航栏:

    self.navigationItem.rightBarButtonItem = yourBarButtonItem;
    

    请记住,此代码进入导航控制器视图控制器数组内的视图控制器。所以基本上,这个“可触摸的图像栏按钮项目”只会在显示这个视图控制器时出现在导航栏中。当您按下另一个视图控制器时,此导航栏按钮项将消失。

    【讨论】:

      【解决方案7】:

      您可能想要覆盖包含您的UIImageView 子视图的UIView(或子类)的touchesBegan:withEvent: 方法。

      在此方法中,测试任何UITouch 触摸是否落在UIImageView 实例的范围内(假设它被称为imageView)。

      也就是说,CGPoint 元素 [touch locationInView] 是否与 CGRect 元素 [imageView bounds] 相交?查看函数CGRectContainsPoint 来运行这个测试。

      【讨论】:

      • 感谢您的回复。我添加了这样的视图:[navBar addSubview:self.pImage]; // 添加为导航栏的子视图。我已经覆盖了该函数,但该函数从未被调用。我已将 UIImageView 的属性 userInteractionEnabled 设置为 YES。我错过了什么吗?
      • 查看 touchesBegan:withEvent: 方法。搜索引擎上有很多关于其工作原理的示例。
      【解决方案8】:

      首先,您应该放置一个 UIButton,然后您可以为此按钮添加背景图像,或者您需要在按钮上放置一个 UIImageView。

      或者:

      您可以将点击手势添加到 UIImageView,以便在点击 UIImageView 时获得点击动作。

      【讨论】:

        【解决方案9】:

        对于那些正在寻找 Swift 4 解决方案来解决这个问题的人,您可以使用以下方法来检测 UIImageView 上的触摸事件。

        let gestureRecognizer: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(imageViewTapped))
        imageView.addGestureRecognizer(gestureRecognizer)
        imageView.isUserInteractionEnabled = true
        

        然后您需要按如下方式定义选择器:

        @objc func imageViewTapped() {
            // Image has been tapped
        }
        

        【讨论】:

          【解决方案10】:

          在该视图上添加手势。将图像添加到该视图中,然后它也会检测图像上的手势。您可以尝试使用触摸事件的委托方法。那么在这种情况下,它也可能会被检测到。

          【讨论】:

            猜你喜欢
            • 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
            相关资源
            最近更新 更多