Manipulando evento de toque em UILabel e conectando-o a um IBAction

101

Ok, então eu UILabelcriei um construtor de interface que exibe algum texto padrão de "toque para começar".

Quando o usuário toca em UILabel, quero acionar um método IBAction: -(IBAction)next;que atualiza o texto do rótulo para dizer algo novo.
Seria muito conveniente se isso me permitisse simplesmente arrastar uma conexão do meu método para a minha etiqueta e, em seguida, selecionar retocar dentro, como com um botão. mas, infelizmente, nada de charuto.

Então, de qualquer forma, minha pergunta é: vou ter que criar uma subclasse UILabelpara fazer isso funcionar? Ou há alguma maneira de arrastar um botão sobre o rótulo, mas torná-lo 0% opaco. Ou existe uma solução mais simples que estou perdendo?

Wfbarksdale
fonte

Respostas:

255

Confira:

UILabel *label = ...
label.userInteractionEnabled = YES;
UITapGestureRecognizer *tapGesture =
      [[UITapGestureRecognizer alloc] initWithTarget:self 
                                              action:@selector(labelTap)];
[label addGestureRecognizer:tapGesture];

O truque é permitir a interação do usuário.

Scott Persinger
fonte
1
E se eu tiver vários rótulos? como posso diferenciar qual foi aproveitado?
aluno de
1
@learner tente a propriedade tag. certifique-se de usar labelTap: em vez de labelTap. e use - (void) labelTap: (id) sender ;.
thedjaney
1
@thedjaney O remetente é o UITapGestureRecognizer, não o UILabel
h4labs de
TapGestureRecognizer não é o mesmo que retocar por dentro e perde a conformidade e acessibilidade da interface humana.
1
@ h4labs você pode usar UITapGestureRecognizer * tapGesture = sender; em seguida, obtenha a etiqueta do rótulo com tapGesture.view.tag
DJTano
70

UILabel herda de UIView que herda de UIResponder. Todos os objetos UIresponder podem manipular eventos de toque. Portanto, em seu arquivo de classe que conhece sua visualização (que contém o UIlabel), implemente:

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

No construtor de interface, defina o valor da tag UILabel. quando os toques ocorrem em seu método touchesBegan, verifique o valor da tag da visualização à qual a tag pertence:

UITouch *touch = [touches anyObject];

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

Você conecta seu código em seu arquivo de classe com o objeto UILabel no construtor de interface, declarando sua variável de instância UILabel com o prefixo IBOutlet:

IBOutlet UILabel *label;

Então, no construtor de interface, você pode conectá-los.

Removedor
fonte
31
Uma observação: você deve certificar-se de marcar "Interação do usuário ativada" no construtor de interface, ou isso não funcionará.
midas06
Eu encontrei um problema com este método. Funcionou bem quando o controlador de visualização foi carregado diretamente, mas quando eu criei um controlador de navegação, empurrei o controlador que contém o rótulo para o controlador de navegação e, em seguida, exibi-lo, os toques não parecem mais chegar ao rótulo. Alguma ideia?
midas06
se for a mesma classe de controlador de visualização que você está empurrando, deve funcionar. parece que pode haver algum outro pequeno problema. talvez comece outra pergunta e poste algum código
Removedor
5
Um método semelhante que não requer etiquetas é simplesmente verificar se touch.view é igual à saída que você definiu para a etiqueta. Prefiro isso, pois significa que não preciso controlar as tags.
Desfragmentado em
ótima solução. Eu recomendo que você não defina nenhuma tag como 0 porque clicar em qualquer outro lugar tem um valor de tag de 0. Isso ocorre porque sua visualização provavelmente terá um valor de tag de 0. Caso contrário, você pode definir a tag de sua visualização como algo como -1 e então você pode usar o valor da tag de 0 em outro lugar, ou seja, um botão
kevinl
30

Você pode usar um UIButton, torná-lo transparente, ou seja, um tipo personalizado sem uma imagem, e adicionar um UILabel nele (centralizado). Em seguida, conecte os eventos de botão normais.

Eiko
fonte
Eu concordo, o tipo de botão personalizado deve fornecer uma experiência de usuário do tipo UILabel.
stitz
2
+1, bonito e simples. Eu tinha tentado isso antes, definindo um botão normal para opactiy 0 que não funcionou, mas a dica para alterar o tipo para personalizado funcionou perfeitamente.
Brian Moeskau
A opacidade afetará o botão e todas as suas subvisualizações, portanto, opacidade = 0 tornará tudo invisível.
Eiko
10
Caramba. Este é um hack em comparação com as outras soluções neste tópico. Use um reconhecedor de gestos de tocar em uma etiqueta se quiser reconhecer um gesto de tocar em uma etiqueta. (Veja como parece que foi feito para isso?)
James Boutcher
Esta é uma solução muito, muito melhor porque os botões lidam com retoques internos, em vez de apenas toques (iniciar).
17

Swift 3

Você tem um IBOutlet

@IBOutlet var label: UILabel!

No qual você ativa a interação do usuário e adiciona um reconhecedor de gestos

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

E finalmente, manuseie a torneira

func userDidTapLabel(tapGestureRecognizer: UITapGestureRecognizer) {
  // Your code goes here
}
César Cruz
fonte
2
Tive que adicionar @objc ao userDidTapLabel para fazer isso funcionar. Pode ser uma coisa rápida.
Compatível com POSIX