【发布时间】:2019-04-15 05:56:34
【问题描述】:
默认布局管理器填充没有文本(最后一行除外)的背景颜色(通过 NSAttributedString .backgroundColor 属性指定)。
我已经通过子类化 NSLayoutManager 并覆盖 func drawBackground(forGlyphRange glyphsToShow: NSRange, at origin: CGPoint) 来实现我想要的效果,如下所示:
override func drawBackground(forGlyphRange glyphsToShow: NSRange, at origin: CGPoint) {
guard let textContainer = textContainers.first, let textStorage = textStorage else { fatalError() }
// This just takes the color of the first character assuming the entire container has the same background color.
// To support ranges of different colours, you'll need to draw each glyph separately, querying the attributed string for the
// background color attribute for the range of each character.
guard textStorage.length > 0, let backgroundColor = textStorage.attribute(.backgroundColor, at: 0, effectiveRange: nil) as? UIColor else { return }
var lineRects = [CGRect]()
// create an array of line rects to be drawn.
enumerateLineFragments(forGlyphRange: glyphsToShow) { (_, usedRect, _, range, _) in
var usedRect = usedRect
let locationOfLastGlyphInLine = NSMaxRange(range)-1
// Remove the space at the end of each line (except last).
if self.isThereAWhitespace(at: locationOfLastGlyphInLine) {
let lastGlyphInLineWidth = self.boundingRect(forGlyphRange: NSRange(location: locationOfLastGlyphInLine, length: 1), in: textContainer).width
usedRect.size.width -= lastGlyphInLineWidth
}
lineRects.append(usedRect)
}
lineRects = adjustRectsToContainerHeight(rects: lineRects, containerHeight: textContainer.size.height)
for (lineNumber, lineRect) in lineRects.enumerated() {
guard let context = UIGraphicsGetCurrentContext() else { return }
context.saveGState()
context.setFillColor(backgroundColor.cgColor)
context.fill(lineRect)
context.restoreGState()
}
}
private func isThereAWhitespace(at location: Int) -> Bool {
return propertyForGlyph(at: location) == NSLayoutManager.GlyphProperty.elastic
}
但是,这不能处理属性字符串中由范围指定的多种颜色的可能性。我怎样才能做到这一点?我看过fillBackgroundRectArray,但收效甚微。
【问题讨论】:
-
看看这个:github.com/kimikaza/TagFieldDemoPlayground/blob/master/… 这样你就可以为每种颜色设置不同的属性键。
-
Koen,谢谢你,但是它不能在多行上工作,但是
-
是的 - 最后,我不再使用属性,而是自己跟踪选定的范围,并根据需要对它们进行着色。但是我没有像你显示的那些空白(在单词 when 之后),所以它也可能不适用于你的情况。
标签: ios swift core-text textkit nslayoutmanager