Como fazer o UILabel responder ao toque?

94

Eu descobri que posso criar UILabel muito mais rápido do que UITextField e planejo usar UILabel na maioria das vezes para meu aplicativo de exibição de dados.

Para encurtar a história, porém, desejo permitir que o usuário toque em um UILabel e que meu retorno de chamada responda a isso. Isso é possível?

Obrigado.

Feliz
fonte
1
Você precisa especificaruserInteractionEnabled = true
onmyway133,

Respostas:

208

Você pode adicionar uma UITapGestureRecognizerinstância ao seu UILabel.

Por exemplo:

UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(labelTapped)];
tapGestureRecognizer.numberOfTapsRequired = 1;
[myLabel addGestureRecognizer:tapGestureRecognizer];
myLabel.userInteractionEnabled = YES;
pythonquick
fonte
13
Aha, a propriedade 'userInteractionEnabled' aqui é a chave (uma vez que a outra configuração pode e deve ser definida preferencialmente em storyboards). O padrão da etiqueta para desativar a interação de modo a passar os toques por meio deles - mas, neste caso, eles precisam observar os toques para que o reconhecedor de gestos seja ativado. Obrigado!
Marchy
1
Agradável! Eu estava apenas tocando em um rótulo e esqueci totalmente de permitir a interação do usuário. Obrigado!
Mike Critchley
37

Se estiver usando storyboards, você pode fazer todo esse processo no storyboard sem nenhum código adicional. Adicione um rótulo ao storyboard e, em seguida, adicione um gesto de toque ao rótulo. No painel Utilitários, certifique-se de que "Interação do usuário habilitada" esteja marcada para o rótulo. Com o gesto de toque (na parte inferior do controlador de visualização no storyboard), ctrl + clique e arraste para o arquivo ViewController.h e crie uma ação. Em seguida, implemente a ação no arquivo ViewController.m.

Leenyburger
fonte
Método também disponível usando o construtor de interface sozinho sem storyboards
Gomino
Certifique-se de que a opção "Interação do usuário habilitada" esteja marcada na seção Exibir no inspetor de atributos , não apenas as características de acessibilidade.
SeanR
17

Swift 3.0

Inicialize o gesto para tempLabel

tempLabel?.text = "Label"
let tapAction = UITapGestureRecognizer(target: self, action: #selector(self.actionTapped(_:)))
tempLabel?.isUserInteractionEnabled = true
tempLabel?.addGestureRecognizer(tapAction)

Receptor de ação

func actionTapped(_ sender: UITapGestureRecognizer) {
    // code here
}

Swift 4.0

Inicialize o gesto para tempLabel

tempLabel?.text = "Label"
let tapAction = UITapGestureRecognizer(target: self, action:@selector(actionTapped(_:)))
tempLabel?.isUserInteractionEnabled = true
tempLabel?.addGestureRecognizer(tapAction)

Receptor de ação

func actionTapped(_ sender: UITapGestureRecognizer) {
    // code here
}
Koushik
fonte
Como obter o texto do rótulo do objeto remetente? Em outras palavras, como identificar o remetente?
Vineel
A versão Swift 4 tem @selector em vez de #selector.
Kirby Todd
8

Swift 2.0:

Estou adicionando uma string nsmutável como texto do sampleLabel, permitindo a interação do usuário, adicionando um gesto de toque e acionar um método.

override func viewDidLoad() {
    super.viewDidLoad()

    let newsString: NSMutableAttributedString = NSMutableAttributedString(string: "Tap here to read the latest Football News.")
    newsString.addAttributes([NSUnderlineStyleAttributeName: NSUnderlineStyle.StyleDouble.rawValue], range: NSMakeRange(4, 4))
    sampleLabel.attributedText = newsString.copy() as? NSAttributedString

    let tapGesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "tapResponse:")
    tapGesture.numberOfTapsRequired = 1
    sampleLabel.userInteractionEnabled =  true
    sampleLabel.addGestureRecognizer(tapGesture)

}
func tapResponse(recognizer: UITapGestureRecognizer) {
    print("tap")
}
AG
fonte
4

Você poderia usar um UIButton em vez disso e definir o texto como você deseja. O botão não precisa se parecer com um botão se você não quiser

Matt S.
fonte
1
Com relação a isso, sempre tive problemas com o UIButton justificando texto de várias linhas à esquerda. Mesmo quando eu defino o alinhamento à esquerda para o centro, ainda acontece.
Feliz
Eu dei uma chance ao UIButton e é muito bom. São apenas os botões multilinhas que são um problema. Obrigado.
Feliz
3

Para adicionar o gesto de toque em UILable

UITapGestureRecognizer *tapAction = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(lblClick:)];
tapAction.delegate =self;
tapAction.numberOfTapsRequired = 1;

//Enable the lable UserIntraction
lblAction.userInteractionEnabled = YES;
[lblAction addGestureRecognizer:tapAction];   

e para avaliar o método seletor

- (void)lblClick:(UITapGestureRecognizer *)tapGesture {

}

Nota: Adicione UIGestureRecognizerDelegate no arquivo .h

Hardik Thakkar
fonte
2

Versão Swift: var tapGesture : UITapGestureRecognizer = UITapGestureRecognizer()

Então viewDidLoad(), dentro , adicione isto:

  let yourLbl=UILabel(frame: CGRectMake(x,y,width,height)) as UILabel!

    yourLbl.text = "SignUp"
    tapGesture.numberOfTapsRequired = 1
    yourLbl.addGestureRecognizer(tapGesture)
    yourLbl.userInteractionEnabled = true
    tapGesture.addTarget(self, action: "yourLblTapped:")
Aditya Jha
fonte
1

Se você quiser usar texto UILabelmultilinha em seu botão, crie um com texto multilinha e adicione como uma subvisualização em seu botão.

por exemplo:

yourLabel=[Uilabel alloc]init];
yourLabel.frame=yourButtom.Frame;//(frame size should be equal to your button's frame)
[yourButton addSubView:yourLabel]
Chandramani
fonte
1

Swift 3 de Alvin George

override func viewDidLoad() {
    super.viewDidLoad()
    let newsString: NSMutableAttributedString = NSMutableAttributedString(string: "Tap here to read the latest Football News.")
    newsString.addAttributes([NSUnderlineStyleAttributeName: NSUnderlineStyle.styleDouble.rawValue], range: NSMakeRange(4, 4))
    sampleLabel.attributedText = newsString.copy() as? NSAttributedString

    let tapGesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(ViewController.tapResponse))
    tapGesture.numberOfTapsRequired = 1
    sampleLabel.isUserInteractionEnabled =  true
    sampleLabel.addGestureRecognizer(tapGesture)
}

func tapResponse(recognizer: UITapGestureRecognizer) {
    print("tap")
}
MRustamzade
fonte
0

A versão Swift tem esta aparência:

func addGestureRecognizerLabel(){
    //Create a instance, in this case I used UITapGestureRecognizer,
    //in the docs you can see all kinds of gestures
    let gestureRecognizer = UITapGestureRecognizer()

    //Gesture configuration
    gestureRecognizer.numberOfTapsRequired = 1
    gestureRecognizer.numberOfTouchesRequired = 1
    /*Add the target (You can use UITapGestureRecognizer's init() for this)
    This method receives two arguments, a target(in this case is my ViewController) 
    and the callback, or function that you want to invoke when the user tap it view)*/
    gestureRecognizer.addTarget(self, action: "showDatePicker")

    //Add this gesture to your view, and "turn on" user interaction
    dateLabel.addGestureRecognizer(gestureRecognizer)
    dateLabel.userInteractionEnabled = true
}

//How you can see, this function is my "callback"
func showDatePicker(){
    //Your code here
    print("Hi, was clicked")
}

//To end just invoke to addGestureRecognizerLabel() when
//your viewDidLoad() method is called

override func viewDidLoad() {
    super.viewDidLoad()
    addGestureRecognizerLabel()
}
LeoGalante
fonte
0

Eu pessoalmente prefiro o método de escrever uma extensão para UILabel. É isso que eu uso.

import UIKit

extension UILabel {
    /**
     * A map of actions, mapped as [ instanceIdentifier : action ].
     */
    private static var _tapHandlers = [String:(()->Void)]()

    /**
     * Retrieve the address for this UILabel as a String.
     */
    private func getAddressAsString() -> String {
        let addr = Unmanaged.passUnretained(self).toOpaque()
        return "\(addr)"
    }

    /**
     * Set the on tapped event for the label
     */
    func setOnTapped(_ handler: @escaping (()->Void)) {
        UILabel._tapHandlers[getAddressAsString()] = handler
        let gr = UITapGestureRecognizer(target: self, action: #selector(onTapped))
        gr.numberOfTapsRequired = 1
        self.addGestureRecognizer(gr)
        self.isUserInteractionEnabled = true
    }

    /**
     * Handle the tap event.
     */
    @objc private func onTapped() {
        UILabel._tapHandlers[self.getAddressAsString()]?()
    }
}

Você então o usaria desta forma a partir de qualquer instância UILabel:

myLabel.setOnTapped {
    // do something
}

Acredito que isso possa causar alguns vazamentos de memória, mas ainda não determinei a melhor forma de resolvê-los.

Nathan F.
fonte