Create tap-able “links” in the NSAttributedString of a UILabel?

前端 未结 30 3209
半阙折子戏
半阙折子戏 2020-11-22 02:07

I have been searching this for hours but I\'ve failed. I probably don\'t even know what I should be looking for.

Many applications have text and in this text are web

30条回答
  •  说谎
    说谎 (楼主)
    2020-11-22 02:48

    Translating @samwize's Extension to Swift 4:

    extension UITapGestureRecognizer {
        func didTapAttributedTextInLabel(label: UILabel, inRange targetRange: NSRange) -> Bool {
            guard let attrString = label.attributedText else {
                return false
            }
    
            let layoutManager = NSLayoutManager()
            let textContainer = NSTextContainer(size: .zero)
            let textStorage = NSTextStorage(attributedString: attrString)
    
            layoutManager.addTextContainer(textContainer)
            textStorage.addLayoutManager(layoutManager)
    
            textContainer.lineFragmentPadding = 0
            textContainer.lineBreakMode = label.lineBreakMode
            textContainer.maximumNumberOfLines = label.numberOfLines
            let labelSize = label.bounds.size
            textContainer.size = labelSize
    
            let locationOfTouchInLabel = self.location(in: label)
            let textBoundingBox = layoutManager.usedRect(for: textContainer)
            let textContainerOffset = CGPoint(x: (labelSize.width - textBoundingBox.size.width) * 0.5 - textBoundingBox.origin.x, y: (labelSize.height - textBoundingBox.size.height) * 0.5 - textBoundingBox.origin.y)
            let locationOfTouchInTextContainer = CGPoint(x: locationOfTouchInLabel.x - textContainerOffset.x, y: locationOfTouchInLabel.y - textContainerOffset.y)
            let indexOfCharacter = layoutManager.characterIndex(for: locationOfTouchInTextContainer, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
            return NSLocationInRange(indexOfCharacter, targetRange)
        }
    }
    

    To set up the recognizer (once you colored the text and stuff):

    lblTermsOfUse.isUserInteractionEnabled = true
    lblTermsOfUse.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTapOnLabel(_:))))
    

    ...then the gesture recognizer:

    @objc func handleTapOnLabel(_ recognizer: UITapGestureRecognizer) {
        guard let text = lblAgreeToTerms.attributedText?.string else {
            return
        }
    
        if let range = text.range(of: NSLocalizedString("_onboarding_terms", comment: "terms")),
            recognizer.didTapAttributedTextInLabel(label: lblAgreeToTerms, inRange: NSRange(range, in: text)) {
            goToTermsAndConditions()
        } else if let range = text.range(of: NSLocalizedString("_onboarding_privacy", comment: "privacy")),
            recognizer.didTapAttributedTextInLabel(label: lblAgreeToTerms, inRange: NSRange(range, in: text)) {
            goToPrivacyPolicy()
        }
    }
    

提交回复
热议问题