在UILabel中处理触摸事件并将其连接到IBAction

106

好的,我在界面构建器中创建了一个UILabel,显示一些默认文本"tap to begin"。

当用户点击UILabel时,我希望它会触发一个IBAction方法:-(IBAction)next;,该方法会更新标签上的文本内容并显示新的信息。
如果可以像按钮一样,仅需将方法与标签拖动连接,然后选择“touch up inside”就太方便了。但是很遗憾,这是不可能的。

所以,我的问题是,我是否需要创建UILabel子类才能使其正常工作?或者是否可以将按钮拖到标签上,但将其透明度设置为0%?还是我漏掉了更简单的解决方法?

4个回答

257

看一下:

UILabel *label = ...
label.userInteractionEnabled = YES;
UITapGestureRecognizer *tapGesture =
      [[UITapGestureRecognizer alloc] initWithTarget:self 
                                              action:@selector(labelTap)];
[label addGestureRecognizer:tapGesture];
关键是启用用户交互。

1
如果我有多个标签,我该如何区分哪一个被点击了? - learner
1
@learner 请尝试使用tag属性。确保使用labelTap:而不是labelTap。并且使用-(void) labelTap:(id)sender;。 - thedjaney
1
@thedjaney 发送者是UITapGestureRecognizer,而不是UILabel。 - h4labs
TapGestureRecognizer并不等同于touch up inside,且会失去人机界面的一致性和可访问性。 - user246672
1
@h4labs 你可以使用UITapGestureRecognizer *tapGesture = sender; 然后通过tapGesture.view.tag获取标签的标记。 - DJTano

70

UILabel继承自UIView,而UIView又继承自UIResponder。所有的UIResponder对象都可以处理触摸事件。在知道你的视图(包含UILabel)的类文件中实现:

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

在界面构建器中设置UILabel的标记值。当你的touchesBegan方法接收到触摸事件时,检查视图的标记值:

UITouch *touch = [touches anyObject];

if(touch.view.tag == MY_TAG_VAL)
label.text = @"new text";

通过在类文件中声明带有 IBOutlet 前缀的 UILabel 实例变量,您可以将代码与 Interface Builder 中的 UILabel 对象连接起来:

IBOutlet UILabel *label;

然后在界面构建器中,您可以将它们连接起来。


31
请确保在界面构建器中勾选“启用用户交互”,否则此功能无法正常工作。 - midas06
我在使用这种方法时遇到了一个问题。当视图控制器直接加载时,它可以正常工作,但是当我创建了一个导航控制器,将包含标签的控制器推送到导航控制器中并显示它时,触摸似乎无法再传递到标签上了。有什么想法吗? - midas06
如果您正在推送相同的视图控制器类,则应该可以工作。听起来可能存在其他一些小问题。也许可以开始另一个问题并发布一些代码。 - Remover
5
一种不需要标签的类似方法是简单地检查 touch.view 是否等于你为标签设置的出口。我更喜欢这种方法,因为这意味着我不必跟踪标签。 - Defragged
很好的解决方案。我建议您不要将任何标签设置为0,因为单击其他位置的标签值为0。这是因为您的视图很可能具有标签值为0。否则,您可以将视图的标签设置为-1,然后您可以在其他地方使用标签值0,例如一个按钮。 - kevinl

31

你可以使用UIButton,将其设为透明,即自定义类型且没有图像,并在其上添加一个居中的UILabel。然后链接正常的按钮事件。


我同意,自定义按钮类型应该给您提供UILabel类型的用户体验。 - stitz
2
+1,简单易懂。我之前尝试过将普通按钮设置为透明度0,但没有成功,但是将类型更改为自定义的提示完美地解决了问题。 - Brian Moeskau
不透明度将影响按钮及其所有子视图,因此opacity=0将使整个内容不可见。 - Eiko
10
哎呀,与本主题中其他解决方案相比,这种方法有点简陋。如果要在标签上识别点击手势,请使用“tap gesture recognizer”(点击手势识别器)。(看看它是不是就是为此而设计的?) - James Boutcher
这是一个更好的解决方案,因为按钮处理touchupinside而不仅仅是轻敲(开始)。 - user246672
@JamesBoutcher 看看这个问题的日期。UIGestureRecognizer是全新的(在iPhone上只有几天)。如果你想针对任何旧设备,它是不可用的。今天,我认为它是一个有效的替代方案。只需使用最能表现意图的方法 - 如果它真的像一个按钮一样工作,就使用一个按钮;如果它只是一些“带有自定义操作但不经常被点击”的文本,请使用手势识别器。 - Eiko

22

Swift 3

你有一个IBOutlet

@IBOutlet var label: UILabel!

您需要启用用户交互并添加手势识别器。

label.isUserInteractionEnabled = true
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(userDidTapLabel(tapGestureRecognizer:)))
label.addGestureRecognizer(tapGesture)

最后,处理轻触操作

func userDidTapLabel(tapGestureRecognizer: UITapGestureRecognizer) {
  // Your code goes here
}

5
为了使这个程序能够运行,我不得不在userDidTapLabel函数前添加@objc。可能是Swift 4的一个问题。 - POSIX-compliant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接