使用NSAttributedString的UILabel的NSForegroundColorAttributeName

时间:2016-07-13 22:26:25

标签: ios swift uilabel nsattributedstring textkit

我有NSAttributed字符串,其中包含链接,我想在UILabel中加载它。我工作正常,但所有链接都是蓝色。

let string = NSMutableAttributedString(attributedString: attributedText)
string.addAttributes([NSForegroundColorAttributeName:linkColor], range: linkRange)
self.attributedText = string

不改变前景色,设置所有其他属性,如删除线样式。只是链接总是保持蓝色。

NSAttributed字符串是从HTML生成的,如果这有任何区别的话。

1 个答案:

答案 0 :(得分:0)

结束了

class AttributedTextLabel:UILabel {

var attributedString:NSAttributedString?{
    didSet{
        guard let attributedString = attributedString else {
            return
        }
        let mutableAttributedString = NSMutableAttributedString(attributedString: attributedString)

        mutableAttributedString.enumerateAttribute(NSLinkAttributeName, inRange: NSRange(location: 0, length: attributedString.length), options: NSAttributedStringEnumerationOptions.Reverse) {[weak self] (attribute, range, other) in

            if let url = attribute as? NSURL {
                mutableAttributedString.removeAttribute(NSLinkAttributeName, range: range)
                self?.links.append(Link(url: url, range: range))
            }
        }
        self.attributedText = mutableAttributedString

    }
}

struct Link {
    var url:NSURL
    var range:NSRange
}

var links:[Link] = []

var edgeInsets:UIEdgeInsets = UIEdgeInsetsZero

private var textContentSize:CGSize {
    let textContainerWidth = frame.width - edgeInsets.left - edgeInsets.right
    let textContainerHeight = frame.height - edgeInsets.top - edgeInsets.bottom

    return CGSizeMake(textContainerWidth, textContainerHeight)
}


func characterIndexAtPoint(point:CGPoint) -> Int? {
    guard let attributedText = attributedText else {
        return nil
    }

    let layoutManager = NSLayoutManager()
    let textContainer = NSTextContainer(size: textContentSize)

    textContainer.lineFragmentPadding = 0.0
    textContainer.lineBreakMode = self.lineBreakMode
    textContainer.maximumNumberOfLines = self.numberOfLines
    layoutManager.addTextContainer(textContainer)

    let storage = NSTextStorage(attributedString: attributedText)
    storage.addLayoutManager(layoutManager)
    let adjustedPoint = CGPointMake(point.x-edgeInsets.left, point.y-edgeInsets.top)

    let characterIndex = layoutManager.characterIndexForPoint(point, inTextContainer: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)

    return characterIndex
}

override func drawTextInRect(rect: CGRect) {
    return super.drawTextInRect(UIEdgeInsetsInsetRect(rect, edgeInsets))
}

private var selectedRange:NSRange?

private var highligtedLink:Link? {
    didSet{
        let string = self.attributedText as! NSMutableAttributedString
        if let oldValue = oldValue {
            if let selectedLinkColor = NativeTextKit.TextAttributes.selectedLinkColor.value {
                string.addAttributes([
                    NSForegroundColorAttributeName:selectedLinkColor
                    ], range: oldValue.range)
            }
        }

        if let highligtedLink = highligtedLink {
            if let selectedLinkColor = NativeTextKit.TextAttributes.selectedLinkColor.value {
                string.addAttributes([
                    NSForegroundColorAttributeName:selectedLinkColor
                    ], range: highligtedLink.range)
            }
        }

        self.attributedText = string
    }
}

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    guard let touch = touches.first else {
        return
    }
    let char = characterIndexAtPoint(touch.locationInView(self))
    let string = self.attributedText as! NSMutableAttributedString

    highligtedLink = linkForTouch(touch)

    string.addAttributes([
        NSForegroundColorAttributeName:UIColor.brownColor()
        ], range: NSMakeRange(char!, 1))

    attributedText = string
}

func linkForTouch(touch:UITouch)->Link? {
    guard let attributedText = attributedText else {
        return nil
    }
    guard let characterIndex = characterIndexAtPoint(touch.locationInView(self)) else {
        return nil
    }
    return links.filter({NSLocationInRange(characterIndex, $0.range)}).first
}

override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {
    highligtedLink = nil
}

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
    guard let touch = touches.first else {
        return
    }
    if let highligtedLink = highligtedLink, let lastTouchedLink = linkForTouch(touch) where highligtedLink.url == lastTouchedLink.url {
        urlInteractionHandler?(textView: UITextView(), url:lastTouchedLink.url)
    }

}

/// Executed on link interaction
var urlInteractionHandler:URLInteractionHandler?
}

这项工作是否需要一段时间才能弄明白。因为UILabel有自己的链接格式结束

  • 设置字符串后,从属性字符串中删除所有链接
  • 将链接和范围添加到数组
  • 选择链接后,使用NSTextContainer确定字符的索引
  • 查找该角色所属的范围
  • 返回链接