UITextView with hyperlink text

后端 未结 10 710
抹茶落季
抹茶落季 2020-11-27 19:23

With a non-editable UITextView, I would like to embed text like this in iOS9+:

Just click here to register

I can create a functi

相关标签:
10条回答
  • 2020-11-27 19:50

    The same solution for Swift 4 using extensions:

    extension UITextView {
    
    
        func hyperLink(originalText: String, hyperLink: String, urlString: String) {
    
                let style = NSMutableParagraphStyle()
                style.alignment = .left
    
                let attributedOriginalText = NSMutableAttributedString(string: originalText)
                let linkRange = attributedOriginalText.mutableString.range(of: hyperLink)
                let fullRange = NSMakeRange(0, attributedOriginalText.length)
                attributedOriginalText.addAttribute(NSAttributedStringKey.link, value: urlString, range: linkRange)
                attributedOriginalText.addAttribute(NSAttributedStringKey.paragraphStyle, value: style, range: fullRange)
                attributedOriginalText.addAttribute(NSAttributedStringKey.foregroundColor, value: UIColor.blue, range: fullRange)
                attributedOriginalText.addAttribute(NSAttributedStringKey.font, value: UIFont.systemFont(ofSize: 10), range: fullRange)
    
                self.linkTextAttributes = [
                   kCTForegroundColorAttributeName: UIColor.blue,
                   kCTUnderlineStyleAttributeName: NSUnderlineStyle.styleSingle.rawValue,
                ] as [String : Any]
    
    
                self.attributedText = attributedOriginalText
            }
    
    }
    
    0 讨论(0)
  • 2020-11-27 19:58

    Swift 4 code. May be I'm the only one who needs to set several links and color the words in one message. I created an AttribTextHolder class to accumulate all information about text inside this holder and easily pass it between objects to set text to UITextView somewhere deep inside a controller.

    class AttribTextHolder {
    
            enum AttrType {
                case link
                case color
            }
    
            let originalText: String
            var attributes: [(text: String, type: AttrType, value: Any)]
    
    
            init(text: String, attrs: [(text: String, type: AttrType, value: Any)] = [])
            {
                originalText = text
                attributes = attrs
            }
    
            func addAttr(_ attr: (text: String, type: AttrType, value: Any)) -> AttribTextHolder {
                attributes.append(attr)
                return self
            }
    
            func setTo(textView: UITextView)
            {
                let style = NSMutableParagraphStyle()
                style.alignment = .left
    
                let attributedOriginalText = NSMutableAttributedString(string: originalText)
    
                for item in attributes {
                    let arange = attributedOriginalText.mutableString.range(of: item.text)
                    switch item.type {
                    case .link:
                        attributedOriginalText.addAttribute(NSAttributedString.Key.link, value: item.value, range: arange)
                    case .color:
                        var color = UIColor.black
                        if let c = item.value as? UIColor { color = c }
                        else if let s = item.value as? String { color = s.color() }
                        attributedOriginalText.addAttribute(NSAttributedString.Key.foregroundColor, value: color, range: arange)
                    default:
                        break
                    }
                }
    
                let fullRange = NSMakeRange(0, attributedOriginalText.length)
                attributedOriginalText.addAttribute(NSAttributedString.Key.paragraphStyle, value: style, range: fullRange)
    
                textView.linkTextAttributes = [
                    kCTForegroundColorAttributeName: UIColor.blue,
                    kCTUnderlineStyleAttributeName: NSUnderlineStyle.styleSingle.rawValue,
                ] as [String : Any]
    
                textView.attributedText = attributedOriginalText
            }
     }
    

    Use it like this:

     let txt = AttribTextHolder(text: "To find out more visit our website or email us your questions")
                .addAttr((text: "our website", type: .link, "http://example.com"))
                .addAttr((text: "our website", type: .color, "#33BB22"))
                .addAttr((text: "email us", type: .link, "mailto:us@example.com"))
                .addAttr((text: "email us", type: .color, UIColor.red))
     ....
     ....
     txt.setTo(textView: myUITextView)
    

    Also in this code I use simple String extension to convert String hex values into UIColor objects

    extension String {
    /// Converts string color (ex: #23FF33) into UIColor
    func color() -> UIColor {
        let hex = self.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
        var int = UInt32()
        Scanner(string: hex).scanHexInt32(&int)
        let a, r, g, b: UInt32
        switch hex.characters.count {
        case 3: // RGB (12-bit)
            (a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
        case 6: // RGB (24-bit)
            (a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF)
        case 8: // ARGB (32-bit)
            (a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
        default:
            (a, r, g, b) = (255, 0, 0, 0)
        }
        return UIColor(red: CGFloat(r) / 255, green: CGFloat(g) / 255, blue: CGFloat(b) / 255, alpha: CGFloat(a) / 255)
      }
    }
    
    0 讨论(0)
  • 2020-11-27 19:59

    A safer solution to implement hyperlink via UITextView

    var termsConditionsTextView: UITextView = {
    let view = UITextView()
     view.backgroundColor = .clear
     view.textAlignment = .left
     
     let firstTitleString = "By registering for THIS_APP I agree with the "
     let secondTitleString = "Terms & Conditions"
     let finishTitleString = firstTitleString + secondTitleString
     let attributedString = NSMutableAttributedString(string: finishTitleString)
     attributedString.addAttribute(.link, value: "https://stackoverflow.com", range: NSRange(location: firstTitleString.count, length: secondTitleString.count))
     
     view.attributedText = attributedString
     view.textContainerInset = .zero
     view.linkTextAttributes = [
         .foregroundColor: UIColor.blue,
         .underlineStyle: NSUnderlineStyle.single.isEmpty
     ]
     
     view.font = view.font = UIFont(name: "YOUR_FONT_NAME", size: 16)
     view.textColor = UIColor.black
     
     return view }()
    
    0 讨论(0)
  • 2020-11-27 20:02

    You could use this simple method to add a hyperlink to any set of characters starting with tag

    func addLink(forString string : NSMutableAttributedString
            ,baseURL : String
            ,tag : String){
            let array = string.string.replacingOccurrences(of: "\n", with: " ").components(separatedBy: " ")
            let filterArray = array.filter { (string) -> Bool in
                return string.contains(tag)
            }
            for element in filterArray {
                let removedHashtag = element.replacingOccurrences(of: tag, with: "")
                let url = baseURL + removedHashtag
                let range = NSString.init(string: (string.string)).range(of: element)
                string.addAttributes([NSAttributedStringKey.link : url.replacingOccurrences(of: " ", with: "")], range: range)
            }
        }
    
    0 讨论(0)
  • 2020-11-27 20:03

    I wanted to do the same thing and ended up just using a UIButton with the title "click here" surrounded by UILabels "just " and " to register", and then:

    @IBAction func btnJustClickHereLink(_ sender: UIButton) {
        if let url = URL(string: "http://example.com") {
            UIApplication.shared.openURL(url)
        }
    }
    
    0 讨论(0)
  • 2020-11-27 20:04

    Set isEditable = false or the text view will go into text-editing mode when user taps on it.

    Swift 4 and later

    let attributedString = NSMutableAttributedString(string: "Just click here to register")
    let url = URL(string: "https://www.apple.com")!
    
    // Set the 'click here' substring to be the link
    attributedString.setAttributes([.link: url], range: NSMakeRange(5, 10))
    
    self.textView.attributedText = attributedString
    self.textView.isUserInteractionEnabled = true
    self.textView.isEditable = false
    
    // Set how links should appear: blue and underlined
    self.textView.linkTextAttributes = [
        .foregroundColor: UIColor.blue,
        .underlineStyle: NSUnderlineStyle.single.rawValue
    ]
    
    0 讨论(0)
提交回复
热议问题