Daniele B
Daniele B

Reputation: 20442

How to make a UILabel clickable?

I would like to make a UILabel clickable.

I have tried this, but it doesn't work:

class DetailViewController: UIViewController {

    @IBOutlet weak var tripDetails: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
        ...
        let tap = UITapGestureRecognizer(target: self, action: Selector("tapFunction:"))
        tripDetails.addGestureRecognizer(tap)
    }

    func tapFunction(sender:UITapGestureRecognizer) {
        print("tap working")
    }
}

Upvotes: 174

Views: 166594

Answers (12)

kutay
kutay

Reputation: 21

On top of all of the other answers, this depends on where the label is, it might be behind some subviews. You might think you tap on the label but maybe click the top view. To solve this you can bring the label view to the front with the following line.

self.view.bringSubviewToFront(lblView)

Upvotes: 0

Md. Arif
Md. Arif

Reputation: 518

Thanks researcher

Here's my solution for programmatic user interface using UIKit.

I've tried it only on Swift 5. And It worked.

Fun fact is you don't have to set isUserInteractionEnabled = true explicitly.

import UIKit

open class LabelButon: UILabel {
    var onClick: () -> Void = {}
    
    public override init(frame: CGRect) {
        super.init(frame: frame)
        isUserInteractionEnabled = true
    }
    
    public required init?(coder: NSCoder) {
        super.init(coder: coder)
    }
    
    public convenience init() {
        self.init(frame: .zero)
    }
    
    open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        onClick()
    }
}

Uses:

override func viewDidLoad() {
    super.viewDidLoad()
    
    let label = LabelButton()
    label.text = "Label"
    label.onClick = {
        // TODO
    }
}

Don't forget to set constraints. Otherwise it won't appear on view.

Upvotes: 4

devbot10
devbot10

Reputation: 1253

Pretty easy to overlook like I did, but don't forget to use UITapGestureRecognizer rather than UIGestureRecognizer.

Upvotes: 3

Jerry Chong
Jerry Chong

Reputation: 9240

Swift 5

Similar to @liorco, but need to replace @objc with @IBAction.

class DetailViewController: UIViewController {

    @IBOutlet weak var tripDetails: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
        ...

        let tap = UITapGestureRecognizer(target: self, action: #selector(DetailViewController.tapFunction))
        tripDetails.isUserInteractionEnabled = true
        tripDetails.addGestureRecognizer(tap)
    }

    @IBAction func tapFunction(sender: UITapGestureRecognizer) {
        print("tap working")
    }
}

This is working on Xcode 10.2.

Upvotes: 32

Claudiu Iordache
Claudiu Iordache

Reputation: 2235

Have you tried to set isUserInteractionEnabled to true on the tripDetails label? This should work.

Upvotes: 209

researcher
researcher

Reputation: 1788

Good and convenient solution:

In your ViewController:

@IBOutlet weak var label: LabelButton!

override func viewDidLoad() {
    super.viewDidLoad()

    self.label.onClick = {
        // TODO
    }
}

You can place this in your ViewController or in another .swift file(e.g. CustomView.swift):

@IBDesignable class LabelButton: UILabel {
    var onClick: () -> Void = {}
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        onClick()
    }
}

In Storyboard select Label and on right pane in "Identity Inspector" in field class select LabelButton.

Don't forget to enable in Label Attribute Inspector "User Interaction Enabled"

Upvotes: 16

liorco
liorco

Reputation: 1493

Swift 3 Update

Replace

Selector("tapFunction:")

with

#selector(DetailViewController.tapFunction)

Example:

class DetailViewController: UIViewController {

    @IBOutlet weak var tripDetails: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
        ...

        let tap = UITapGestureRecognizer(target: self, action: #selector(DetailViewController.tapFunction))
        tripDetails.isUserInteractionEnabled = true
        tripDetails.addGestureRecognizer(tap)
    }

    @objc
    func tapFunction(sender:UITapGestureRecognizer) {
        print("tap working")
    }
}

Upvotes: 132

Amr Angry
Amr Angry

Reputation: 3851

As described in the above solution you should enable the user interaction first and add the tap gesture

this code has been tested using

Swift4 - Xcode 9.2

yourlabel.isUserInteractionEnabled = true
yourlabel.addGestureRecognizer(UITapGestureRecognizer(){
                //TODO 
            })

Upvotes: -4

Xcodian Solangi
Xcodian Solangi

Reputation: 2408

SWIFT 4 Update

 @IBOutlet weak var tripDetails: UILabel!

 override func viewDidLoad() {
    super.viewDidLoad()

    let tap = UITapGestureRecognizer(target: self, action: #selector(GameViewController.tapFunction))
    tripDetails.isUserInteractionEnabled = true
    tripDetails.addGestureRecognizer(tap)
}

@objc func tapFunction(sender:UITapGestureRecognizer) {

    print("tap working")
}

Upvotes: 55

DURGESH
DURGESH

Reputation: 2453

For swift 3.0 You can also change gesture long press time duration

label.isUserInteractionEnabled = true
let longPress:UILongPressGestureRecognizer = UILongPressGestureRecognizer.init(target: self, action: #selector(userDragged(gesture:))) 
longPress.minimumPressDuration = 0.2
label.addGestureRecognizer(longPress)

Upvotes: 3

Abhishek
Abhishek

Reputation: 509

You need to enable the user interaction of that label.....

For e.g

yourLabel.userInteractionEnabled = true

Upvotes: 4

Indrajit Sinh Rayjada
Indrajit Sinh Rayjada

Reputation: 1243

Swift 3 Update

yourLabel.isUserInteractionEnabled = true

Upvotes: 16

Related Questions