How to get UILabel to respond to tap?
Asked Answered
V

12

101

I have discovered that I can create UILabel much faster than UITextField and I plan to use UILabel most of the time for my data display app.

To make a long story short though, I wish to let the user tap on a UILabel and have my callback respond to that. Is that possible?

Thanks.

Victual answered 22/8, 2011 at 22:27 Comment(1)
You need to specify userInteractionEnabled = trueAnamorphic
M
220

You can add a UITapGestureRecognizer instance to your UILabel.

For example:

UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(labelTapped)];
tapGestureRecognizer.numberOfTapsRequired = 1;
[myLabel addGestureRecognizer:tapGestureRecognizer];
myLabel.userInteractionEnabled = YES;
Malefaction answered 22/8, 2011 at 22:29 Comment(2)
Aha, the 'userInteractionEnabled' property here is key (since the other configuration can and should preferably be set in storyboards). Label's default the interaction to off so as to pass through touches through them - but in this case they need to observe touches for the gesture recognizer to activate. Thanks!Discriminating
Nice one! I was just throwing a tap onto a label and totally forgot to enable user interaction. Thanks!Prerequisite
O
39

If you're using storyboards you can do this entire process in the storyboard with no additional code. Add a label to the storyboard, then add a tap gesture to the label. In the Utilities pane, make sure "User Interaction Enabled" is checked for the label. From the tap gesture (at the bottom of your view controller in the storyboard), ctrl+click and drag to your ViewController.h file and create an Action. Then implement the action in the ViewController.m file.

Octachord answered 18/3, 2014 at 18:24 Comment(2)
Method also available using interface builder alone without storyboardsArithmetic
Make sure "User Interaction Enabled" is checked under the View section in the Attributes inspector, not just the Accessibility Traits.Sternmost
D
18

Swift 3.0

Initialize the gesture for tempLabel

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

Action receiver

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

Swift 4.0

Initialize the gesture for tempLabel

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

Action receiver

func actionTapped(_ sender: UITapGestureRecognizer) {
    // code here
}
Domela answered 15/3, 2017 at 12:31 Comment(2)
How to get the label text from the sender object ? In other words how to identify the sender?Spinks
Swift 4 version has @selector instead of #selector.Gittel
F
8

Swift 2.0:

I am adding a nsmutable string as sampleLabel's text, enabling user interaction, adding a tap gesture and trigger a method.

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")
}
Franzen answered 11/2, 2016 at 9:52 Comment(0)
R
4

You could use a UIButton instead and set the text to what you want. The button doesn't have to look like a button if you don't want to

Raeannraeburn answered 22/8, 2011 at 22:30 Comment(2)
As regards that, I have always had trouble with UIButton left-justifying multi-line text. Even when I set the left alignment to center it still happens.Victual
I did give UIButton a try though and it is pretty nice. It's just the multi-line buttons that are a problem. Thanks.Victual
W
4

To add Tap gesture on 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];   

and to assess the selector method

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

}

Note: Add UIGestureRecognizerDelegate in .h file

Walloon answered 2/10, 2015 at 7:21 Comment(0)
S
2

Swift Version: var tapGesture : UITapGestureRecognizer = UITapGestureRecognizer()

Then inside viewDidLoad(),add this:

  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:")
Simas answered 9/5, 2016 at 7:27 Comment(0)
F
2

This works great in Xcode 12 and Swift 5

let tapAction = UITapGestureRecognizer(target: self,action:#selector(actionTapped(_:)))

userLabel?.isUserInteractionEnabled = true

userLabel?.addGestureRecognizer(tapAction)

And action method like -

@objc func actionTapped(_ sender: UITapGestureRecognizer) {
        print("tapped")
    }
Francescafrancesco answered 21/11, 2020 at 19:15 Comment(0)
E
1

If you want to use Multi line text in your button then create a UILabel with Multiline text and add as a subview in to your button.

for eg:

yourLabel=[Uilabel alloc]init];
yourLabel.frame=yourButtom.Frame;//(frame size should be equal to your button's frame)
[yourButton addSubView:yourLabel]
Expander answered 3/4, 2013 at 10:29 Comment(0)
S
1

Swift 3 from 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")
}
Sumikosumma answered 5/10, 2016 at 17:37 Comment(0)
S
0

Swift version looks like this:

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()
}
Starobin answered 31/1, 2016 at 6:5 Comment(0)
B
0

I personally prefer the method of writing an extension for UILabel. This is what I use.

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()]?()
    }
}

You would then use it like this from any UILabel instance:

myLabel.setOnTapped {
    // do something
}

This can potentially cause some memory leaks I believe, but I haven't determined how best to resolve them yet.

Bannerol answered 25/10, 2019 at 21:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.