Link to the relevant sample project
描述
我正在尝试创建一个自定义的NSCollectionViewLayout子类,它使用自动布局来确定其项目的大小。此布局从上到下放置项目,其中所有项目共享相同的宽度,但每个项目的高度由其内容决定。可以把它看作是macOS的UITableView布局。
假设
初始布局属性在布局的prepare()方法中计算,并通过layoutAttributesForElements(in:)提供给集合视图。集合视图使用这些属性来确定需要显示哪些项。这些项由集合视图的委托提供,并调用每个项的apply(_:)方法来设置其视图属性。
然后,集合视图将调用项的preferredLayoutAttributesFitting(_:)方法来计算其内容的适合大小。然后,返回的属性将被传递给集合视图布局的shouldInvalidateLayout(forPreferredLayoutAttributes:withOriginalAttributes:)方法,在该方法中,布局将确定是否需要根据新属性进行调整,并将该布尔决策返回给集合视图。
如果布局决定需要使其无效,则集合视图将调用invalidationContext(forPreferredLayoutAttributes:withOriginalAttributes:)来从布局中获取有关如何更新自身的特定信息。然后,当集合视图调用invalidationContext(forPreferredLayoutAttributes:withOriginalAttributes:)时,布局可以应用这些更改。
然后重复此过程,直到shouldInvalidateLayout(forPreferredLayoutAttributes:withOriginalAttributes:)为每个布局项目返回false -提示集合视图在屏幕上显示这些项目。
前提
NSCollectionViewLayout的ListLayout子类能够为每个NSCollectionViewItem创建一组初始布局属性,其中包含10点的“估计”初始高度。我们希望使用Auto Layout来确定每个项目的实际高度,所以这个初始值应该无关紧要。
然后,布局能够通过layoutAttributesForElements(in:)提供这些初始属性的正确集合。
NSCollectionViewItem的TextFieldItem子类包含一个NSTextField实例,该实例同时设置为其view和textField属性。此视图的translatesAutoresizingMaskIntoConstraints属性设置为false,并且具有必需的垂直内容压缩阻力优先级。该项的apply(_:)方法被重写,以将文本字段的preferredMaxLayoutWidth设置为给定属性提供的宽度。该项的preferredLayoutAttributesFitting(_:)方法被重写,以将首选属性的高度设置为与文本字段的intrinsicContentSize属性相等。
集合视图提供了填充了多行文本的TextFieldItem实例。
预计每个TextFieldItem都会在其apply(_:)方法之后调用其preferredLayoutAttributesFitting(_:)方法,然后调用布局的shouldInvalidateLayout(forPreferredLayoutAttributes:withOriginalAttributes:)和invalidationContext(forPreferredLayoutAttributes:withOriginalAttributes:)方法。
但是,当操场运行时,preferredLayoutAttributesFitting(_:)、shouldInvalidateLayout(forPreferredLayoutAttributes:withOriginalAttributes:)或invalidationContext(forPreferredLayoutAttributes:withOriginalAttributes:)都不会被调用。因此,每一项的高度都保持在初始的“估计”高度。

问题
关于NSCollectionViewLayout和自动布局,我肯定遗漏了一些东西,但我在文档中没有找到任何东西来表明这一点。
我尝试在集合视图的生命周期中的各个不同点手动调用这些方法,但没有任何方法能够正确触发布局以调整其计算的属性。
是否需要在集合视图、其布局或项上设置属性以指示应调用preferredLayoutAttributesFitting(_:)?自动布局是否仅支持NSCollectionViewFlowLayout和NSCollectionViewGridLayout的子类?或者我误解了NSCollectionViewLayout实例的生命周期?
发布于 2018-09-26 11:04:52
我也有同样的问题,这是我的解决方案,它工作得很完美。将以下代码添加到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])
}https://stackoverflow.com/questions/52468731
复制相似问题