繁体   English   中英

对自定义文本视图的自动布局支持

[英]Autolayout support for custom text view

这个问题是关于使用约束和视图的用于自动布局的内在内容大小来支持可变高度的自定义文本视图。 在您单击“复制”按钮之前,请听我说完。

我有一个自定义文本视图(从头开始,从 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 做了一些不同的事情(假设 'Editable' 关闭,'Wrap' 开启)。 它的内在内容大小在单行上报告文本的全宽(即使它比可用宽度长得多),但它以某种方式调整为正确的宽度。 调整大小后,内在内容宽度仍会报告完整的单行宽度,但会调整高度以考虑多行。 某处有一些我无法预知的魔法。

我已经阅读了相关文档的每一行。 如果有关于该主题的博客文章,我可能已经阅读过。 如果有关于该主题的 SO 问题,我可能已经阅读过。 如果你写了一本关于这个主题的书,我可能已经买了它。 所有这些来源都在嘲笑我遇到的问题,但没有一个回答如何处理这种特殊情况的问题。 绝望的。

更新:

在阅读了 Jonathon Mah 的一篇旧博文( http://devetc.org/code/2014/07/07/auto-layout-and-views-that-wrap.html )后,我创建了一个使用他的方法的示例。 这是另一个模仿他的技术并正常工作的项目 这是应用程序的顶部。 这是一个用滑块调整的固定容器视图。 拼凑是自定义视图的伪字符,其背景为粉红色。

在此处输入图片说明

但是,当插入到自调整表格视图中时,自定义视图正确匹配其单元格的宽度,但未调整单元格以尊重固有高度。 如果您将自定义视图的底部约束更改为可选(例如,使用 >= 关系),自定义视图确实会缩小到正确的高度,但单元格视图保持固定。 如何说服单元格视图缩小其高度以尊重其子视图的内在内容尺寸.高度?

在此处输入图片说明

我对您的问题有一个解决方案,尽管它可能不是最佳解决方案,因为我对 macos 的细节没有太多经验。 所以,首先,让我们定义 table view 应该使用自动行高:

override func awakeFromNib() {
    super.awakeFromNib()
    tableView.usesAutomaticRowHeights = true
}

在您的第二个示例中, tableView 插座没有连接到TableViewController ,但它可能应该连接,所以不要忘记连接它。

现在,在您的WrappingCellView ,您覆盖了layout() ,但您为preferredMaxLayoutWidth设置的值不正确。 我认为应该是superview的宽度:

override func layout() {
    // 16 is used for the sake of example
    wrappingView.preferredMaxLayoutWidth = (superview?.frame.width ?? 16) - 16
    super.layout()
}

下一部分是我不确定的部分:

func tableViewColumnDidResize(_ notification: Notification) {
    tableView.reloadData()
}

应该有更好的 API 来重新计算行高。 我希望你或其他人可以提出一些建议:)

这三个调整导致正确重新计算单元高度: 在此处输入图片说明

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM