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
-提示收集视图以在屏幕上显示项目。
ListLayout
的{{1}}子类能够为每个NSCollectionViewLayout
创建一个初始的布局属性集,其初始高度为NSCollectionViewItem
点。我们期望使用“自动布局”来确定每个项目的实际高度,因此该初始值应该无关紧要。
然后,布局可以通过10
提供这些初始属性的正确集合。
layoutAttributesForElements(in:)
的{{1}}子类包含一个TextFieldItem
实例,该实例被设置为其NSCollectionViewItem
和NSTextField
属性。此视图的view
属性设置为false,并具有所需的垂直内容压缩优先级。覆盖项的textField
方法可将文本字段的translatesAutoresizingMaskIntoConstraints
设置为给定属性提供的宽度。覆盖该项的apply(_:)
方法可将首选属性的高度设置为等于文本字段的preferredMaxLayoutWidth
属性。
向集合视图提供了preferredLayoutAttributesFitting(_:)
实例,其中填充了多行文本。
预计每个intrinsicContentSize
将在其TextFieldItem
方法之后调用其TextFieldItem
方法,然后调用布局的preferredLayoutAttributesFitting(_:)
和{{1} }方法。
但是,游乐场运行时,apply(_:)
,shouldInvalidateLayout(forPreferredLayoutAttributes:withOriginalAttributes:)
和invalidationContext(forPreferredLayoutAttributes:withOriginalAttributes:)
都不会被调用。结果,每个项目的高度都保持在初始的“估计”高度。
关于preferredLayoutAttributesFitting(_:)
和“自动版式”,我肯定缺少一些东西,但是我在文档中没有发现任何指示。
我尝试在集合视图的生命周期的各个不同点手动调用这些方法,但是没有任何方法能够正确触发布局以调整其归类属性。
是否需要在集合视图,其布局或指示shouldInvalidateLayout(forPreferredLayoutAttributes:withOriginalAttributes:)
的项目上设置属性? invalidationContext(forPreferredLayoutAttributes:withOriginalAttributes:)
和NSCollectionViewLayout
的子类仅支持自动版式吗?还是我误解了preferredLayoutAttributesFitting(_:)
实例的生命周期?
答案 0 :(得分: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])
}