这个问题是关于使用约束和视图的intrinsicContentSize 来支持可变高度的自定义文本视图以进行自动布局。在您单击“复制”按钮之前,请听我说完。
我有一个自定义文本视图(从头开始,继承自 NSView)。它支持许多常见的 NSTextView 功能,这里最相关的是多行并根据可用宽度布置其内容。它构建的应用程序将这些文本视图中的几个加载到表格视图的每一行中。问题是没有根据它的内在内容大小正确设置高度。
我创建了一个简化问题的示例项目。它使用具有固定数量和大小的字符的“伪”文本视图,用于确定所需的宽度/高度。在示例中,有一列的表格视图,其单元格视图只有一个子视图,即 PseudoTextView。文本视图被固定在其单元格视图的边缘,并带有一点填充。如何让系统识别文本视图应该遵守定义宽度的约束,同时允许文本视图在高度上增长,并被单元格视图紧紧包裹?这是文本视图代码:
class PseudoTextView: NSView {
@IBInspectable var characterCount: Int = 0
@IBInspectable var characterWidth: CGFloat = 5
@IBInspectable var characterHeight: CGFloat = 8
@IBInspectable var background: NSColor = .blue {
didSet {
layer?.backgroundColor = background.cgColor
}
}
required init?(coder decoder: NSCoder) {
super.init(coder: decoder)
wantsLayer = true
layer?.backgroundColor = background.cgColor
}
override var intrinsicContentSize: NSSize {
let requiredWidth = characterWidth * CGFloat(characterCount)
let lineCount = (requiredWidth / frame.width).rounded(.up)
let usedHeight = lineCount * characterHeight
let charactersPerLine = (frame.width / characterWidth).rounded(.down)
let usedWidth = charactersPerLine * characterWidth
return NSSize(width: usedWidth, height: usedHeight)
}
此版本根据视图的框架返回适当的大小。这显然不起作用,因为它是在布局的 updateConstraints 阶段在尚未设置框架时访问的。我也尝试使用 NSView.noIntrinsicMetric 作为宽度,但这会将文本视图驱动为零宽度并且高度永远不会恢复。我还做了很多其他尝试,但我不会全部让你厌烦。
NSTextField 做了一些不同的事情(假设“可编辑”关闭,“包装”打开)。它的 intrinsicContentSize 在一行上报告文本的全宽(即使它比可用宽度长得多),但它以某种方式调整为正确的宽度。调整大小后,intrinsicContentWidth 仍会报告完整的单行宽度,但会调整高度以适应多行。在我无法预测的地方有一些魔法。
我已经阅读了相关文档的每一行。如果有关于该主题的博客文章,我可能已经阅读过。如果关于这个话题有关于 SO 的问题,我可能已经读过了。如果你写了一本关于这个主题的书,我可能已经买了。所有这些消息来源都在取笑我遇到的问题,但没有一个能回答如何处理这种特殊情况的问题。绝望的。
更新:
在阅读了 Jonathon Mah 的一篇旧博客文章 ( http://devetc.org/code/2014/07/07/auto-layout-and-views-that-wrap.html ) 之后,我创建了一个使用他的方法的示例。这是另一个模仿他的技术并正常工作的项目。这是应用程序的顶部。这是一个使用滑块调整的固定容器视图。拼凑是自定义视图的伪字符,其背景是粉红色。
但是,当插入到自调整大小的表格视图中时,自定义视图会正确匹配其单元格的宽度,但不会调整单元格以尊重固有高度。如果您将自定义视图的底部约束更改为可选的(例如,使用 >= 关系),自定义视图会缩小到正确的高度,但单元格视图保持固定。如何说服单元格视图缩小其高度以尊重其子视图的intrinsicContentSize.height?