Swift : tap on a part of text of UILabel

前端 未结 7 985
北海茫月
北海茫月 2020-12-02 21:36

I have a problem that \"boundingRectForGlyphRange\" always returns CGRect.zero \"0.0, 0.0, 0.0, 0.0\". \"boundingRectForGlyphRange\" is not working. For example, I am coding

7条回答
  •  情深已故
    2020-12-02 22:06

    This is a real easy alternative for anyone who is willing to use a textView. I realize this question is about a UILabel but if you read the comments on some of the answers they don't work for some people and some of them are very code heavy which isn't very good for beginners. You can do this in 11 simple steps if your willing to swap out a UILabel for a UITextView.

    You can use NSMutableAttributedString and a UITextView. The UITextView has a delegate method: func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool { ... }. Once you set the part of the string that you want to make tappable the delegate method will activate it.

    The 11 steps are listed below in the comments above each piece of code.

    // 1st **BE SURE TO INCLUDE** UITextViewDelegate to the view controller's class
    class VewController: UIViewController, UITextViewDelegate {
    
        // 2nd use a programmatic textView or use the textView from your storyboard
        lazy var yourTextView: UITextView = {
            let textView = UITextView()
            textView.textAlignment = .center
            textView.isEditable = false
            textView.showsVerticalScrollIndicator = false
            return textView
        }()
    
       override func viewDidLoad() {
            super.viewDidLoad()
    
            // 3rd in viewDidLoad set the textView's delegate
            yourTextView.delegate = self
    
            // 4th create the first piece of the string you don't want to be tappable
            let regularText = NSMutableAttributedString(string: "any text ", attributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 17), NSAttributedStringKey.foregroundColor: UIColor.black])
    
            // 5th create the second part of the string that you do want to be tappable. I used a blue color just so it can stand out.
            let tappableText = NSMutableAttributedString(string: "READ MORE")
            tappableText.addAttribute(NSAttributedString.Key.font, value: UIFont.systemFont(ofSize: 17), range: NSMakeRange(0, tappableText.length))
            tappableText.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.blue, range: NSMakeRange(0, tappableText.length))
    
            // 6th this ISN'T NECESSARY but this is how you add an underline to the tappable part. I also used a blue color so it can match the tappableText and set the value to 1 for the line height. The length of the underline is based on the tappableText's length using NSMakeRange(0, tappableText.length)
            tappableText.addAttribute(NSAttributedString.Key.underlineStyle, value: 1, range: NSMakeRange(0, tappableText.length))
            tappableText.addAttribute(NSAttributedString.Key.underlineColor, value: UIColor.blue, range: NSMakeRange(0, tappableText.length))
    
            // 7th this is the important part that connects the tappable link to the delegate method in step 11
            // use NSAttributedString.Key.link and the value "makeMeTappable" to link the NSAttributedString.Key.link to the method. FYI "makeMeTappable" is a name I choose for clarity, you can use anything like "anythingYouCanThinkOf"
            tappableText.addAttribute(NSAttributedString.Key.link, value: "makeMeTappable", range: NSMakeRange(0, tappableText.length))
    
            // 8th *** important append the tappableText to the regularText ***
            regularText.append(tappableText)
    
            // 9th set the regularText to the textView's attributedText property
            yourTextView.attributedText = regularText 
       }
    
       // 10th add the textView's delegate method that activates urls. Make sure to return false for the tappable part
       func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool {
        
            // 11th use the value from the 7th step to trigger the url inside this method
            if URL.absoluteString == "makeMeTappable" {
    
                // in this situation I'm using the tappableText to present a view controller but it can be used for whatever you trying to do
                let someVC = SomeController()
                let navVC = UINavigationController(rootViewController: someVC)
                present(navVC, animated: true, completion: nil)
    
                return false // *** IMPORTANT return false for this to actually work ***
            }
    
            return true
        }
    }
    

提交回复
热议问题