【问题标题】:NSTableView has unwanted space above first rowNSTableView 在第一行上方有多余的空间
【发布时间】:2020-07-30 14:19:15
【问题描述】:

我有一个 NSTableView,它的第一行从顶部向下推 10 pt。标题关闭,没有分组行,单元格间距为 0,封闭滚动视图的内容插入为 0。


更新

这里有一个 sample project 来演示这个问题。


这是视图层次调试器的抓取:

这是第一行的NSTableRowView 在视图层次调试器中暂停时的垂直约束:

我尝试实现委托的tableView(_:didAdd:forRow:) 并检查约束,首先使用constraintsAffectingLayout(for:)

[<NSLayoutConstraint:0x60000390bd40 'NSTableRowView_Encapsulated_Layout_Height' NSTableRowView:0x7fdb12e26eb0.height == 24 priority:500   (active)>]

然后打印所有行视图的constraints:

  - 0 : <NSLayoutConstraint:0x60000390bcf0 'NSTableRowView_Encapsulated_Layout_Width' NSTableRowView:0x7fdb12e26eb0.width == 329 priority:500   (active)>
  - 1 : <NSLayoutConstraint:0x60000390bd40 'NSTableRowView_Encapsulated_Layout_Height' NSTableRowView:0x7fdb12e26eb0.height == 24 priority:500   (active)>
  - 2 : <NSAutoresizingMaskLayoutConstraint:0x60000390bbb0 h=--& v=-&- InlineCell.minX == 16   (active, names: InlineCell:0x7fdb12e283a0, '|':NSTableRowView:0x7fdb12e26eb0 )>
  - 3 : <NSAutoresizingMaskLayoutConstraint:0x60000390bc00 h=--& v=-&- InlineCell.width == 297   (active, names: InlineCell:0x7fdb12e283a0 )>
  - 4 : <NSAutoresizingMaskLayoutConstraint:0x60000390bc50 h=--& v=-&- InlineCell.minY == 0   (active, names: InlineCell:0x7fdb12e283a0, '|':NSTableRowView:0x7fdb12e26eb0 )>
  - 5 : <NSAutoresizingMaskLayoutConstraint:0x60000390bca0 h=--& v=-&- V:[InlineCell]-(0)-|   (active, names: InlineCell:0x7fdb12e283a0, '|':NSTableRowView:0x7fdb12e26eb0 )>

单元格的 minY 约束设置为 0,但该行使用自动调整大小掩码。该表使用简单的 diffable 数据源:

NSTableViewDiffableDataSourceReference(tableView: table) { tableView, column, row, item in
    guard let cell = tableView.makeView(withIdentifier: inlineCellIdentifier, owner: self) as? NSTableCellView else { 
        preconditionFailure("Failed to create results cell") 
    }
    cell.textField?.textColor = self.themeAttributes.color
    cell.textField?.font = self.themeAttributes.font
    cell.textField?.stringValue = self.displayString(for: item)
    return cell
}

唯一实现的委托方法是tableView(_:heightOfRow:)。该表与同级文本视图的行对齐,因此它从那里获取行高:

func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
    guard let layoutManager = editor?.layoutManager else { 
        preconditionFailure("Missing layout manager in editor") 
    }
    return height(of: row, in: layoutManager)
}

这似乎很明显,但我不明白为什么表会强制它的行像这样偏移。我在这个论坛上发现了很多问题,询问如何插入表格顶部的空白,而不是如何删除。有什么建议吗?

【问题讨论】:

  • 单元格间距可能是罪魁祸首吗? (你有我最深切的同情。我目前正在与 NSOutlineView 争论自动布局,它莫名其妙地坚持我的一行的高度限制为 0...)
  • 很遗憾没有。单元格间距为 0,我不希望它应用在第一行之上,对吧?
  • 在自动布局领域一切皆有可能。我现在无法重现此问题 - 您应该编辑您的帖子以更清楚地说明这是 MacOS 11 的问题。 (Diffable Data sources 是我在 WWDC 上错过的一个公告;感谢您指出)。如果它仍然存在,您可能需要为此提交错误。
  • 还有一件事——如果你想让更多的人参与进来,我建议创建一个MRE 一个可以下载并使用它/检查它的人,...
  • 感谢您的建议。 @green_knight:不相信这是一个大苏尔问题,但正如 zrzka 指出的那样,我应该制作一个示例项目来检查它。我会继续努力的——谢谢你让我保持直截了当:)

标签: macos nstableview appkit macos-big-sur


【解决方案1】:

这不是错误,正如某些 cmets 所述,这是 NSTableView 在 Big Sur 中的一种新工作方式(实际上存在错误,但在其他地方,请参见下文)。免费的 Pascal 站点包含 nice overview of what's new

新的NSTableView 属性

macOS Big Sur 引入了新的NSTableView 属性:

style 文档:

在 macOS 11 中,此属性的默认值为 NSTableView.Style.automatic。链接到以前 macOS 版本的应用默认为 NSTableView.Style.fullWidth

effectiveStyle 文档:

如果style 属性值为NSTableView.Style.automatic,则此属性包含已解析的样式。

.automatic documentation:

系统通过以下方式解析表格视图样式:

  • 如果表格视图位于侧边栏拆分视图控制器项中,effectiveStyle 将解析为 NSTableView.Style.sourceList
  • 如果表格的滚动视图有边框,effectiveStyle 将解析为 NSTableView.Style.fullWidth
  • 否则effectiveStyle 解析为NSTableView.Style.inset。但是,如果表格需要额外空间来容纳其列单元格,effectiveStyle 将解析为 NSTableView.Style.fullWidth

您的表格视图在 Main.storyboard 中的样式设置为 .automatic。这意味着有效样式解析为 .inset -> 围绕内容 10pt(基于 .automatic 文档中的规则)。

使用选定的行打开视图调试器。可以看到.inset样式效果:

使用 .fullWidth 删除 10pt 插图。

您还可以测试.automatic 样式的行为 - 尝试为滚动视图添加边框。解析为.fullWidth

错误和解决方法

您可能尝试在界面生成器中将表格视图样式设置为全宽。它不起作用。无论您选择什么值,它的行为都类似于.automatic

将以下行添加到您的代码中以解决此问题:

tableView?.style = .fullWidth

现在按预期工作:

报告为 FB8258910。

【讨论】:

  • 没提,但我确实玩过没有效果的样式。不过,没想到用代码来做。太棒了,先生!
  • 感谢您的详细解释。
  • Xcode (12.0 beta 4 12A8179i) 和 macOS 11.0 Beta 4 20A5343i 的更新。 1) 属性检查器中的样式仍然有点被忽略(行为类似于.automatic,有趣的是唯一未被忽略的选项是Source List)。 2)在代码中设置类型仍然是最可靠的方法。 3) 有一个新的错误 - .inset 类型作物底部的选择背景。
  • 还有.plain 样式表示“没有应用嵌入、填充或任何其他类型的装饰”。这对于需要维护旧视图的应用非常有用。
  • Hmnm,看起来好像没有用于查询插图大小的公共 API。我发现 NSTableView 有一个名为_styleContentInsets() 的私有方法,它返回NSEdgeInsets。在 Big Sur 上,结果是插入顶部:5,底部:10,左/右:16
猜你喜欢
  • 2021-11-03
  • 1970-01-01
  • 1970-01-01
  • 2015-09-02
  • 2020-10-09
  • 2020-09-13
  • 2015-04-22
  • 1970-01-01
  • 2015-11-24
相关资源
最近更新 更多