我试图了解Apple的API如何用于计算文本布局,从而陷入了一个兔子洞。在Text Layout Programming Guide中,有一些示例Objective-C代码覆盖了默认的lineFragmentPadding
并将其设置为0.0:
NSTextStorage *textStorage = [[[NSTextStorage alloc] initWithString:myString] autorelease];
NSTextContainer *textContainer = [[[NSTextContainer alloc] initWithContainerSize: NSMakeSize(myWidth, FLT_MAX)] autorelease];
NSLayoutManager *layoutManager = [[[NSLayoutManager alloc] init] autorelease];
[layoutManager addTextContainer:textContainer];
[textStorage addLayoutManager:layoutManager];
[textStorage addAttribute:NSFontAttributeName value:myFont range:NSMakeRange(0, [textStorage length])];
[textContainer setLineFragmentPadding:0.0];
(void) [layoutManager glyphRangeForTextContainer:textContainer];
return [layoutManager usedRectForTextContainer:textContainer].size.height;
文档中给出的将其设置为0的原因:
将线段填充设置为0以获得准确的宽度测量。 (填充用于页面布局,以防止文本容器中的文本与页面上的其他元素(如图形)紧密相邻。)
好的,但我确实想要lineFragmentPadding
,因为他们提到的原因,所以我按照示例代码但没有使用0.0(我将其设置为5.0,如果不这样做,这是默认值覆盖)。
let textStore = NSTextStorage(string: multilineString)
let textSize = CGSize(width: magicWidth, height: 1000.0)
let container = NSTextContainer(size: textSize)
let layout = NSLayoutManager()
layout.addTextContainer(container)
textStore.addLayoutManager(layout)
container.lineBreakMode = .byWordWrapping
container.lineFragmentPadding = 5.0
在上面的评论中,NSTextContainer的lineFragmentPadding
表示:
NSLayoutManager使用此值来确定布局宽度。
如果它用于设置包装它的文本的布局宽度似乎也会调整高度。但我开始意识到我的高度计算量很少。起初我无法理解为什么,所以我创建了一个带有红色叠加层的简单游乐场,以帮助查看从layout.usedRect(for: container).size
返回的大小。
这是lineFragmentPadding = 0.0
:
layout.usedRect(for:container).size报告的红色叠加层大小为{w 285.697 h 125.062}
这是lineFragmentPadding = 5.0
:
layout.usedRect(for:container).size报告的红色叠加层大小为{w 284.582 h 110.742}
这是一个更夸张的例子,它设置为25.0:
layout.usedRect(for:container).size报告的红色叠加层大小为{w 233.885 h 94.922}
更改容器的lineFragmentPadding
不会更改从layout.usedRect(for: container)
返回的布局大小,但会更改textView中的实际布局。我不明白,为什么我可以应用于NSTextContainer的lineFragmentPadding不会影响布局管理器返回的 sizing 高度?我期待一个线性关系 - 当宽度因为lineFragmentPadding
而缩小时,如果需要换行,应该导致高度增加。看起来相反的情况正在发生
layout.usedRect(for:container).size摘要示例:
lineFragmentPadding = 0.0
,layout.usedRect(for:container){w 285.697 h 125.062}
lineFragmentPadding = 5.0
,layout.usedRect(for:container){w 284.582 h 110.742}
lineFragmentPadding = 25.0
,layout.usedRect(for:container){w 233.885 h 94.922}
编辑1:添加了25.0示例。
编辑2:澄清示例以包含从layout.usedRect(for:container)返回的尺寸