Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does UILabel have any value to make it selectable?

Tags:

ios

uilabel

swift

Does UILabel have any value that can be set in order to make it selectable?

I have a label that I want to be selectable, (long press and a copy btn shows up) kinda like in Safari.

like image 813
user2636197 Avatar asked Oct 11 '16 23:10

user2636197


People also ask

How do you make UILabel selectable?

The steps are as follows: Create a subclass of UILabel which you will use anywhere you want your label text to be selectable. Add a long press gesture recogniser. Upon long press, present the UIMenuController shared instance with the menu items you need, in this case, Copy and Speak.

How do I know if my UILabel is truncated?

With a UILabel you can check for truncation by calculating the size of the text within the label and comparing that with the bounds of the label itself. If the text extends beyond the bounds then it's being displayed as truncated.

Is UILabel a view?

A view that displays one or more lines of informational text.


2 Answers

Self-contained Solution (Swift 5)

You can adapt the solution from @BJHSolutions and NSHipster to make the following self-contained SelectableLabel:

import UIKit

/// Label that allows selection with long-press gesture, e.g. for copy-paste.
class SelectableLabel: UILabel {
    
    override func awakeFromNib() {
        super.awakeFromNib()

        isUserInteractionEnabled = true
        addGestureRecognizer(
            UILongPressGestureRecognizer(
                target: self,
                action: #selector(handleLongPress(_:))
            )
        )
    }

    override var canBecomeFirstResponder: Bool {
        return true
    }
    
    override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        return action == #selector(copy(_:))
    }

    // MARK: - UIResponderStandardEditActions
    
    override func copy(_ sender: Any?) {
        UIPasteboard.general.string = text
    }
    
    // MARK: - Long-press Handler
    
    @objc func handleLongPress(_ recognizer: UIGestureRecognizer) {
        if recognizer.state == .began,
            let recognizerView = recognizer.view,
            let recognizerSuperview = recognizerView.superview {
            recognizerView.becomeFirstResponder()
            UIMenuController.shared.setTargetRect(recognizerView.frame, in: recognizerSuperview)
            UIMenuController.shared.setMenuVisible(true, animated:true)
        }
    }
    
}
like image 165
Chris Chute Avatar answered Sep 18 '22 00:09

Chris Chute


Yes, you need to implement a UIMenuController from a long press gesture applied to your UILabel. There is an excellent article about this on NSHipster, but the gist of the article is the following.

Create a subclass of UILabel and implement the following methods:

override func canBecomeFirstResponder() -> Bool {
    return true
}

override func canPerformAction(action: Selector, withSender sender: AnyObject?) -> Bool {
    return (action == "copy:")
}

// MARK: - UIResponderStandardEditActions

override func copy(sender: AnyObject?) {
    UIPasteboard.generalPasteboard().string = text
}

Then in your view controller, you can add a long press gesture to your label:

let gestureRecognizer = UILongPressGestureRecognizer(target: self, action: "handleLongPressGesture:")
label.addGestureRecognizer(gestureRecognizer)

and handle the long press with this method:

func handleLongPressGesture(recognizer: UIGestureRecognizer) {
     if let recognizerView = recognizer.view,
         recognizerSuperView = recognizerView.superview
     {
         let menuController = UIMenuController.sharedMenuController()
         menuController.setTargetRect(recognizerView.frame, inView: recognizerSuperView)
         menuController.setMenuVisible(true, animated:true)
         recognizerView.becomeFirstResponder()
     }}

NOTE: This code is taken directly from the NSHipster article, I am just including it here for SO compliance.

like image 28
JAB Avatar answered Sep 19 '22 00:09

JAB