0

链接到相关示例项目

描述

我正在尝试创建一个自定义NSCollectionViewLayout子类,该子类使用自动布局来确定其项目的大小。这种布局从上到下定位项目,其中所有项目共享相同的宽度,但每个项目的高度由其内容决定。将其视为UITableViewmacOS 的布局。

假设

初始布局属性在布局的prepare()方法中计算,并通过 layoutAttributesForElements(in:). 集合视图使用这些属性来确定需要显示哪些项目。这些项目由集合视图的委托提供,并apply(_:)调用每个项目的方法来设置其视图属性。

然后集合视图将调用项目的preferredLayoutAttributesFitting(_:)方法来计算其内容的合适大小。然后返回的属性将被传递到集合视图布局的shouldInvalidateLayout(forPreferredLayoutAttributes:withOriginalAttributes:)方法中,其中布局确定是否需要进行调整以响应新属性,并将该布尔决策返回给集合视图。

如果布局决定它需要失效,然后集合视图将调用invalidationContext(forPreferredLayoutAttributes:withOriginalAttributes:)以从布局中获取特定信息,以了解它应该如何自我更新。然后当集合视图调用invalidationContext(forPreferredLayoutAttributes:withOriginalAttributes:)时,布局可以应用这些更改。

然后重复这个过程,直到shouldInvalidateLayout(forPreferredLayoutAttributes:withOriginalAttributes:)返回false每个布局项——提示集合视图在屏幕上显示这些项。

前提

ListLayout子类NSCollectionViewLayout能够为每个NSCollectionViewItem具有“估计”初始高度的10点创建一组初始布局属性。我们期望使用自动布局来确定每个项目的实际高度,所以这个初始值应该无关紧要。

然后,布局能够通过 提供正确的这些初始属性集layoutAttributesForElements(in:)

TextFieldItem子类NSCollectionViewItem包含一个NSTextField实例,该实例同时设置为它的viewtextField属性。此视图的translatesAutoresizingMaskIntoConstraints属性设置为 false,并且具有所需的垂直内容压缩阻力优先级。覆盖项目的apply(_:)方法以将文本字段preferredMaxLayoutWidth设置为给定属性提供的宽度。覆盖项的preferredLayoutAttributesFitting(_:)方法以将首选属性的高度设置为等于文本字段的intrinsicContentSize属性。

集合视图提供了TextFieldItem填充多行文本的实例。

预计每个方法TextFieldItem都会在其preferredLayoutAttributesFitting(_:)方法之后apply(_:)调用,然后调用布局shouldInvalidateLayout(forPreferredLayoutAttributes:withOriginalAttributes:)invalidationContext(forPreferredLayoutAttributes:withOriginalAttributes:)方法。

但是,在操场运行时,都不会调用preferredLayoutAttributesFitting(_:), nor shouldInvalidateLayout(forPreferredLayoutAttributes:withOriginalAttributes:), nor 。invalidationContext(forPreferredLayoutAttributes:withOriginalAttributes:)结果,每个项目的高度都保持在最初的“估计”高度。

每个文本字段应显示三行文本,但只有第一行的顶部可见。

问题

一定有我遗漏的东西NSCollectionViewLayout和自动布局,但我在文档中没有找到任何表明这一点的东西。

我尝试在集合视图生命周期的各个不同点手动调用这些方法,但没有任何方法能够正确触发布局以调整其计算属性。

是否需要在集合视图、其布局或指示preferredLayoutAttributesFitting(_:)应调用的项目上设置属性?自动布局是否仅支持 和 的子NSCollectionViewFlowLayoutNSCollectionViewGridLayout?还是我误解了NSCollectionViewLayout实例的生命周期?

4

1 回答 1

0

我有同样的问题,这是我的解决方案,效果很好。将以下代码添加到 UICollectionViewCell 的子类中。

override func awakeFromNib() {

    super.awakeFromNib()

    self.contentView.translatesAutoresizingMaskIntoConstraints = false

    let leftConstraint = contentView.leftAnchor.constraint(equalTo: leftAnchor)
    let rightConstraint = contentView.rightAnchor.constraint(equalTo: rightAnchor)
    let topConstraint = contentView.topAnchor.constraint(equalTo: topAnchor)
    let bottomConstraint = contentView.bottomAnchor.constraint(equalTo: bottomAnchor)
    NSLayoutConstraint.activate([leftConstraint, rightConstraint, topConstraint, bottomConstraint])
}
于 2018-09-26T03:04:51.547 回答