10.11 NSCollectionView - 动态确定单元大小

时间:2015-11-01 08:19:06

标签: macos cocoa autolayout nscollectionview nscollectionviewitem

AppKit Release Notes for OS X v10.11建议可以按项目调整集合视图项的大小:

  

项目大小可以全局确定所有CollectionView的项目(通过设置NSCollectionViewFlowLayout的“itemSize”属性),或者可以从一个项目到下一个项目不同(通过在CollectionView的委托上实现-collectionView:layout:sizeForItemAtIndexPath: )。

就我而言,我的CollectionViewItem包含一个包含不同长度字符串的标签。我使用NSCollectionView来显示字符串数组,因为NSStackViews不支持数组绑定,并且不会流向新行。字符串数组通过数组控制器绑定到NSCollectionView的内容。

我的项目的nib文件已正确设置,根视图和标签都具有内容拥抱内容压缩阻力优先级1000,以及边缘通过AutoLayout对齐。

现在,NSCollectionViewLayout的委托方法有这个签名:

func collectionView(collectionView: NSCollectionView, 
                    layout collectionViewLayout: NSCollectionViewLayout, 
                    sizeForItemAtIndexPath indexPath: NSIndexPath) -> NSSize

我现在的想法是抓取项目本身,对其进行布局传递,然后返回新项目大小。

let item = collectionView.itemAtIndexPath(indexPath)!
item.view.layout()
return item.view.bounds.size

这种方法的问题是itemAtIndexPath返回nil。如果我以零值返回默认大小,则默认大小将用于所有单元格。

如何设置NSCollectionView以尊重我的项目的AutoLayout约束,并为每个单元格动态使用计算出的大小?

1 个答案:

答案 0 :(得分:4)

我回答了这个问题的重复,但这可能是它应该被引导到的那个,因为它已经老了。

Juul的评论是正确的 - 这些项目不存在。被调用的sizeForItemAt是向代表询问该数据条目的任何特定大小,它将用于帮助创建其最终视图控制器NSCollectionViewItem。因此,当您要求集合为您提供用于帮助获取项目的方法中的项目时,您创建一个循环。

我们遇到的问题是我们希望根据该数据的外观进行调整:具有正确格式的文本标签的长度,而不仅仅是字符串长度。所以我们遇到了鸡和蛋的问题。

我唯一能解决的解决方案如下:

制备

  • 子类NSCollectionViewItem并确保您的集合视图具有返回正确子类项的数据源。
  • 完全使用XIB中的约束。
  • 您的子类应该有一个加载到要表示的数据对象中的方法 - 无论是对此还是数据源协议方法。
  • 在第一个sizeForItemAt调用之前的某个时刻,或者在第一个NSCollectionViewItem调用之前的某个时刻,如果你当时没有,请手动创建instantiate(withOwner:topLevelObjects:)子类的实例,并使用NSNib的{ {1}}将您的子类作为所有者实例化其XIB。将该引用存储为一种“大小调整模板”,因此您只需要执行一次。代表是我最容易找到的地方。

^ 注意:我的第一个路线是通过集合的makeItemWithIdentifier尝试这个,但它更脆,因为它要求集合在创建大小调整模板时有项目。在初始sizeForItemAt期间(在重新加载崩溃期间访问/制作项目)也无法完成。而且我担心因为它是用集合制作的,它可能会被重用,而下面的方法不起作用或开始编辑可见项目。 YMMV。

sizeForItemAt

  • 直接从数据源获取正在表示的数据对象。让您的大小调整模板对象用我前面提到的方法表示该数据对象。
  • 访问大小调整模板View.FittingSize,项目的最小尺寸可以给予其约束/优先级,然后返回。

的Bam!没有经过压力测试或任何事情,但我没有任何问题,它没有做布局通行证或任何事情,只是调用FittingSize。我还没有在网上看到这个,所以我想写出完整的解释。

我在Xamarin.Mac中这样做了,所以我的代码不会是1:1而且我不想写乱码swift并弄乱任何东西。

TLDR:手动实例化一个NSCollectionViewItem子类及其将存储的xib,该集合无需拥有。在sizeForItem期间填充您存储为大小调整引用的项目,并返回集合项目视图的FittingSize