阐明 NSLayoutManager 和 NSTextContainer 在垂直布局方面的行为?
Clarifying the behaviour of NSLayoutManager & NSTextContainer with respect to vertical layout?
代码示例
我有一个 NSLayoutManager, NSTextContainer & NSTextStorage
作为自定义 NSView
(不是 TextView)中的属性,在 awakeFromNib()
中初始化如下:
textStorage = NSTextStorage(attributedString: self.attributedString)
layoutManager = NSLayoutManager()
textContainer = NSTextContainer(containerSize: NSMakeSize(self.frame.size.width, 1))
layoutManager.addTextContainer(textContainer)
textStorage.addLayoutManager(layoutManager)
layoutManager.glyphRangeForTextContainer(textContainer)
NSTextContainer
的垂直 containerSize
被特意设置为 1 以查看它是否具有隐藏正在呈现的文本的预期效果 - 它没有!它在视图中呈现此文本时造成 NO 差异 - 这是问题的主题!
在 drawRect
中,我包括以下几行来绘制文本:
let glyphRange = layoutManager.glyphRangeForTextContainer(textContainer)
self.lockFocus()
layoutManager.drawGlyphsForGlyphRange(glyphRange, atPoint: NSMakePoint(0, 0))
self.unlockFocus()
调查结果
- 似乎最好在像
NSTextView
这样的翻转坐标系中使用您的自定义视图,否则我觉得我将陷入痛苦的世界!不管怎样,NSLayoutManager 总是开始在翻转的坐标系中内部绘制它的文本(就像 NSTextView
)
NSTextContainer
的 containerSize.width
属性 具有以下效果:它在所有级别(包括第一级)的行级别上具有约束力(我知道这很明显,但请坚持我的看法。 ..)
NSTextContainer
的 containerSize.height
属性 有一个曲线球:它不会在第一行绑定 即使 包含视图没有垂直显示它的空间,但将绑定到后续行
*我花了很长时间才得出这个关于containerSize.height
的假设,因为我只画了一条线! *
问题
- 我关于
NSTextContainer
的结论正确吗?
- 从垂直角度控制文本绘制的最佳方式是什么?我想将单行文本放在视图的底部(而不是像默认情况下那样将其浮动在顶部)
NSTextContainer
有一个 containerSize
属性。布局管理器正在布置该容器内的文本。据推测,容器在您的视图中逻辑上位于 (0, 0),但文本是从其顶部开始布局的。所以,容器有松弛。
您可以根据从 -[NSLayoutManager usedRectForTextContainer:]
返回的矩形调整容器的大小以使其适合。
更新:
我认为您 drawRect()
中的这样的代码应该可以实现您想要实现的目标:
layoutManager.ensureLayoutForTextContainer(textContainer)
var rect = layoutManager.usedRectForTextContainer(textContainer)
rect.origin.x += 2
rect.origin.y = NSMaxY(self.bounds) - NSHeight(rect) - 4
let glyphRange = layoutManager.glyphRangeForTextContainer(textContainer)
layoutManager.drawGlyphsForGlyphRange(glyphRange, atPoint:rect.origin)
代码示例
我有一个 NSLayoutManager, NSTextContainer & NSTextStorage
作为自定义 NSView
(不是 TextView)中的属性,在 awakeFromNib()
中初始化如下:
textStorage = NSTextStorage(attributedString: self.attributedString)
layoutManager = NSLayoutManager()
textContainer = NSTextContainer(containerSize: NSMakeSize(self.frame.size.width, 1))
layoutManager.addTextContainer(textContainer)
textStorage.addLayoutManager(layoutManager)
layoutManager.glyphRangeForTextContainer(textContainer)
NSTextContainer
的垂直 containerSize
被特意设置为 1 以查看它是否具有隐藏正在呈现的文本的预期效果 - 它没有!它在视图中呈现此文本时造成 NO 差异 - 这是问题的主题!
在 drawRect
中,我包括以下几行来绘制文本:
let glyphRange = layoutManager.glyphRangeForTextContainer(textContainer)
self.lockFocus()
layoutManager.drawGlyphsForGlyphRange(glyphRange, atPoint: NSMakePoint(0, 0))
self.unlockFocus()
调查结果
- 似乎最好在像
NSTextView
这样的翻转坐标系中使用您的自定义视图,否则我觉得我将陷入痛苦的世界!不管怎样,NSLayoutManager 总是开始在翻转的坐标系中内部绘制它的文本(就像NSTextView
) NSTextContainer
的containerSize.width
属性 具有以下效果:它在所有级别(包括第一级)的行级别上具有约束力(我知道这很明显,但请坚持我的看法。 ..)NSTextContainer
的containerSize.height
属性 有一个曲线球:它不会在第一行绑定 即使 包含视图没有垂直显示它的空间,但将绑定到后续行
*我花了很长时间才得出这个关于containerSize.height
的假设,因为我只画了一条线! *
问题
- 我关于
NSTextContainer
的结论正确吗? - 从垂直角度控制文本绘制的最佳方式是什么?我想将单行文本放在视图的底部(而不是像默认情况下那样将其浮动在顶部)
NSTextContainer
有一个 containerSize
属性。布局管理器正在布置该容器内的文本。据推测,容器在您的视图中逻辑上位于 (0, 0),但文本是从其顶部开始布局的。所以,容器有松弛。
您可以根据从 -[NSLayoutManager usedRectForTextContainer:]
返回的矩形调整容器的大小以使其适合。
更新:
我认为您 drawRect()
中的这样的代码应该可以实现您想要实现的目标:
layoutManager.ensureLayoutForTextContainer(textContainer)
var rect = layoutManager.usedRectForTextContainer(textContainer)
rect.origin.x += 2
rect.origin.y = NSMaxY(self.bounds) - NSHeight(rect) - 4
let glyphRange = layoutManager.glyphRangeForTextContainer(textContainer)
layoutManager.drawGlyphsForGlyphRange(glyphRange, atPoint:rect.origin)