NSAttributedString boundingRect返回错误的高度 [英] NSAttributedString boundingRect returns wrong height
问题描述
我这样计算NSAttributedString
的高度.
let maxSize = NSSize(width: w, height: CGFloat.greatestFiniteMagnitude)
let rect = boundingRect(with: maxSize, options: [.usesFontLeading, .usesLineFragmentOrigin])
let height = rect.integral.size.height
我尝试了SO上提到的每个"hack",但是宽度越小,字符串高度变得越不准确(计算出的高度大于实际高度).
I tried about every "hack" that was mentioned on SO, yet the string height gets more inaccurate the smaller the width gets (the calculated height is larger than the actual height).
根据其他帖子,以下内容会导致尺寸计算出现问题:
According to other posts the following things cause problems with size calculation:
- 空白
- 没有前景色
- 没有背景色
- 低于300的宽度无效(?)
我发现这些建议都没有任何不同.属性字符串是行的串联,每行都有一个foregroundColor
和backgroundColor
.该字符串还具有以下段落样式.
I have found that none of these suggestions make any difference. The attributed string is a concatenation of lines, each having a foregroundColor
and backgroundColor
. The string also has the following paragraph style.
let pstyle = NSMutableParagraphStyle()
pstyle.lineSpacing = 6
pstyle.lineBreakMode = .byWordWrapping
和大小为11的userFixedPitchFont
.
宽度越小,为什么高度误差会变大?
Why does the height error get larger the smaller the width is?
PS:我想这与lineBreak
有关,因为如果用更多的行换行,错误会变得更大.
PS: I imagine it has something to do with lineBreak
since the error gets larger if more lines are word wrapped.
推荐答案
我发现此解决方案有效.请注意,如果您未将lineFragmentPadding
设置为0
,则会产生与boundingRect
相同(错误)的结果.
I found that this solution works. Note that if you don't set the lineFragmentPadding
to 0
, it produces the same (wrong) results as boundingRect
.
extension NSAttributedString {
func sizeFittingWidth(_ w: CGFloat) -> CGSize {
let textStorage = NSTextStorage(attributedString: self)
let size = CGSize(width: w, height: CGFloat.greatestFiniteMagnitude)
let boundingRect = CGRect(origin: .zero, size: size)
let textContainer = NSTextContainer(size: size)
textContainer.lineFragmentPadding = 0
let layoutManager = NSLayoutManager()
layoutManager.addTextContainer(textContainer)
textStorage.addLayoutManager(layoutManager)
layoutManager.glyphRange(forBoundingRect: boundingRect, in: textContainer)
let rect = layoutManager.usedRect(for: textContainer)
return rect.integral.size
}
}
这篇关于NSAttributedString boundingRect返回错误的高度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!