将GestureRecognizer添加到字符串无法正常工作

问题描述 投票:0回答:1

我有一个Label,其中有两个应为words的特定clickable。它是这样的:

enter image description here

NutungsbedigungenDatenschutzrichtlinien都应为clickable。我要做的就是:

setUpLabel:

func setUpDocumentsLabel(){
    var textArray = [String]()
    var fontArray = [UIFont]()
    var colorArray = [UIColor]()
    textArray.append("Mit 'fortfahren' akzeptierst du die")
    textArray.append("Nutzungsbedingungen")
    textArray.append("und")
    textArray.append("Datenschutzrichtlinien.")

    fontArray.append(Fonts.regularFontWithSize(size: 13.0))
    fontArray.append(Fonts.boldFontWithSize(size: 13.0))
    fontArray.append(Fonts.regularFontWithSize(size: 13.0))
    fontArray.append(Fonts.boldFontWithSize(size: 13.0))

    colorArray.append(Colors.white)
    colorArray.append(Colors.white)
    colorArray.append(Colors.white)
    colorArray.append(Colors.white)

    self.documentsLabel.attributedText = getAttributedString(arrayText: textArray, arrayColors: colorArray, arrayFonts: fontArray)

    self.documentsLabel.isUserInteractionEnabled = true
    let tapgesture = UITapGestureRecognizer(target: self, action: #selector(tappedOnLabel(_ :)))
    tapgesture.numberOfTapsRequired = 1
    self.documentsLabel.addGestureRecognizer(tapgesture)
}

tappedAction:

@objc func tappedOnLabel(_ gesture: UITapGestureRecognizer) {
    guard let text = self.documentsLabel.text else { return }
    let nutzen = (text as NSString).range(of: "Nutzungsbedingungen")
    let daten = (text as NSString).range(of: "Datenschutzrichtlinien")

    if gesture.didTapAttributedTextInLabel(label: self.documentsLabel, inRange: nutzen) {

        let alertcontroller = UIAlertController(title: "Tapped on", message: "user tapped on Nutzungsbedingungen", preferredStyle: .alert)
        let alertAction = UIAlertAction(title: "OK", style: .default) { (alert) in

        }
        alertcontroller.addAction(alertAction)
        self.present(alertcontroller, animated: true)

    } else if gesture.didTapAttributedTextInLabel(label: self.documentsLabel, inRange: daten){

        let alertcontroller = UIAlertController(title: "Tapped on", message: "user tapped on Datenschutzrichtlinien", preferredStyle: .alert)
        let alertAction = UIAlertAction(title: "OK", style: .default) { (alert) in

        }
        alertcontroller.addAction(alertAction)
        self.present(alertcontroller, animated: true)

    }
}

getAttributedString:

func getAttributedString(arrayText:[String]?, arrayColors:[UIColor]?, arrayFonts:[UIFont]?) -> NSMutableAttributedString {

    let finalAttributedString = NSMutableAttributedString()

    for i in 0 ..< (arrayText?.count)! {

        let attributes = [NSAttributedString.Key.foregroundColor: arrayColors?[i], NSAttributedString.Key.font: arrayFonts?[i]]
        let attributedStr = (NSAttributedString.init(string: arrayText?[i] ?? "", attributes: attributes as [NSAttributedString.Key : Any]))

        if i != 0 {

            finalAttributedString.append(NSAttributedString.init(string: " "))
        }

        finalAttributedString.append(attributedStr)
    }

    return finalAttributedString
}

问题:

strings不是每个字符上的clickablelength区域的clickable因设备而异:

对于Datenschutzrichtlinien

iPhone 11:来自[[D-t的clickable

iPhone SE:

D-第二个i]的[C0

对于clickable

在除iPhone SE之外的所有设备上均可使用:仅从

N-2nd n

开始我不知道为什么会这样,所以如果有人可以在这里帮助我,我非常感谢!

更新:

我正在将此Nutzungsbedingungen用于extension

UITapGestureRecognizer

ios swift string label nsattributedstring
1个回答
2
投票
您在这里遇到的特定问题是因为标签上有

extension UITapGestureRecognizer { func didTapAttributedTextInLabel(label: UILabel, inRange targetRange: NSRange) -> Bool { // Create instances of NSLayoutManager, NSTextContainer and NSTextStorage let layoutManager = NSLayoutManager() let textContainer = NSTextContainer(size: CGSize.zero) let textStorage = NSTextStorage(attributedString: label.attributedText!) // Configure layoutManager and textStorage layoutManager.addTextContainer(textContainer) textStorage.addLayoutManager(layoutManager) // Configure textContainer textContainer.lineFragmentPadding = 0.0 textContainer.lineBreakMode = label.lineBreakMode textContainer.maximumNumberOfLines = label.numberOfLines let labelSize = label.bounds.size textContainer.size = labelSize // Find the tapped character location and compare it to the specified range 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) }

但是.textAlignment = .center
代码不知道...它基于从

标签的左边缘开始的“ und Datenschutzrichtlinien。”计算位置。您可以尝试解决此问题-快速测试(仅在一台设备上-似乎可以完成这项工作。

在您的didTapAttributedTextInLabel()类中,请勿将文档标签居中:

FirstLaunchViewController

[您似乎只使用过一次let documentsLabel: UILabel = {
    let v = UILabel()
    // don't do this
    //v.textAlignment = .center
    v.numberOfLines = 0
    v.translatesAutoresizingMaskIntoConstraints = false
    return v
}()
,这是为了格式化func getAttributedString(...)的属性文本,所以请如下更改:

documentsLabel

现在,您的func getAttributedString(arrayText:[String]?, arrayColors:[UIColor]?, arrayFonts:[UIFont]?) -> NSMutableAttributedString {

    let finalAttributedString = NSMutableAttributedString()

    for i in 0 ..< (arrayText?.count)! {

        let attributes = [NSAttributedString.Key.foregroundColor: arrayColors?[i], NSAttributedString.Key.font: arrayFonts?[i]]
        let attributedStr = (NSAttributedString.init(string: arrayText?[i] ?? "", attributes: attributes as [NSAttributedString.Key : Any]))

        if i != 0 {

            finalAttributedString.append(NSAttributedString.init(string: " "))
        }

        finalAttributedString.append(attributedStr)
    }

    // add paragraph attribute
    let paragraph = NSMutableParagraphStyle()
    paragraph.alignment = .center
    let attributes: [NSAttributedString.Key : Any] = [NSAttributedString.Key.paragraphStyle: paragraph]
    finalAttributedString.addAttributes(attributes, range: NSRange(location: 0, length: finalAttributedString.length))

    return finalAttributedString
}
函数应该检测相对于“可轻敲”的单词的正确敲击位置。
© www.soinside.com 2019 - 2024. All rights reserved.