【问题标题】:Clarifying the behaviour of NSLayoutManager & NSTextContainer with respect to vertical layout?澄清 NSLayoutManager 和 NSTextContainer 关于垂直布局的行为?
【发布时间】:2015-03-11 18:25:36
【问题描述】:

代码示例

我有一个NSLayoutManager, NSTextContainer & NSTextStorage 作为在awakeFromNib() 中初始化的自定义NSView(不是TextView)中的属性,如下所示:

    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()

调查结果

  1. 似乎最好在翻转坐标系中使用您的自定义视图,例如NSTextView,否则我觉得我将进入一个痛苦的世界!无论如何,NSLayoutManager 总是开始在一个翻转的坐标系统内部绘制它的文本(就像NSTextView
  2. NSTextContainercontainerSize.width 属性具有以下效果:它在行级别上绑定所有级别,包括第一个级别(我知道这很明显,但坚持我...)
  3. NSTextContainercontainerSize.height 属性有一个曲线球:它不会绑定在第一行 即使包含的视图没有空间垂直显示它但会对后续行具有约束力

*我花了很长时间才得出这个关于containerSize.height 的假设,因为我只画了一条线! *

问题

  1. 我关于NSTextContainer 的结论是否正确?
  2. 从垂直角度控制文本绘制的最佳方法是什么?我想将我的单行文本放在视图的底部(而不是像默认情况下那样浮动在顶部)

【问题讨论】:

    标签: objective-c cocoa swift nsview nslayoutmanager


    【解决方案1】:

    NSTextContainer 有一个 containerSize 属性。布局管理器正在布局该容器内的文本。据推测,容器在您的视图中逻辑上位于 (0, 0) 处,但文本从其顶部开始布局。所以,容器有松弛。

    您可以根据从 -[NSLayoutManager usedRectForTextContainer:] 返回的 rect 调整容器的大小以使其适合大小。


    更新:

    我认为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)
    

    【讨论】:

    • layoutManager.usedRectForTextContainer(textContainer) 的结果在 (0,0) 处出现 - 自然这无济于事。奇怪的是,即使我将 textContainer.containerSize 设置为这个 (0,0) 它对渲染的最终视图没有任何作用!?
    • 更奇怪的是:我的视图布局似乎独立于textContainer.containerSize。刚刚玩了一些初始值。
    • -usedRectForTextContainer: 不执行布局。您必须在使用-ensureLayoutForTextContainer: 从中获取有意义的值之前确保布局。不知道其他的东西。
    • 谢谢。通过调用ensureLayoutForTextContainer(...),我现在得到了containerSize 的合理值。但是,仍然没有改变它的渲染方式。
    • FWIW layoutManager.setLocation(NSMakePoint(2, 2), forStartOfGlyphRange: glyphRange) 似乎可以使文本从视图底部开始。使用 (2,2) 因为 (0,0) 实际上会截断一些文本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-09
    • 1970-01-01
    • 1970-01-01
    • 2012-02-15
    • 2014-10-07
    • 2012-10-25
    相关资源
    最近更新 更多