我正在研究我已在Android上开发的应用程序的iOS版本.此应用程序具有以下2列自定义(固定宽度但可变高度)单元格的网格:
在Android版本中实现这一点很容易,因为谷歌提供了StaggeredGridLayoutManager
它RecyclerView
.您可以指定列数和滚动方向.
默认UICollectionView
布局UICollectionViewFlowLayout
不允许我正在寻找的交错布局,所以我必须实现自定义布局.我看过那个谈论这个话题(2个WWDC视频中的新增功能表和收集意见和高级用户界面与集合视图)和我或多或少都有它应该如何实现的想法.
步骤1.首先计算布局的近似值.
步骤2.然后创建单元格并使用自动布局调整大小.
步骤3.然后控制器通知单元格大小,以便更新布局.
在尝试编写这些步骤时,我产生了疑虑.我找到了一个教程,解释了创建具有交错列的自定义布局,但它没有使用autolayout来获取单元格的大小.这让我有以下问题:
在步骤2中,我如何以及何时可以获得单元格大小?
在第3步中,我如何以及何时通知更改的布局?
我想指出的是,正如您已经提到的,RayWenderlich PinInterest Layout正是可以帮助您实现此布局的教程。
要回答您的问题-关于本教程:
在第2步中,如何以及何时获得像元大小?
为了获得像元高度,实现了一个委托方法,该prepareLayout
方法在custom方法中被调用UICollectionViewLayout
。该方法被调用一次(或两次,我只是尝试使用一条print
语句运行它,而我得到了两次调用)。重点prepareLayout
是初始化单元格的frame
属性,换句话说,提供每个单元格的确切大小。我们知道宽度是恒定的,只有height
改变,所以在这行prepareLayout
:
let cellHeight = delegate.collectionView(collectionView!, heightForItemAtIndexPath: indexPath, withWidth: width)
我们从中实现的委托方法获取单元格的高度UICollectionViewController
。对于我们要在中显示的所有单元格,都会发生这种情况collectionView
。在获取并修改了每个像元的高度后,我们缓存结果,以便以后进行检查。
然后,collectionView
要获取屏幕上每个单元的大小,所需要做的就是在缓存中查询信息。这是在layoutAttributesForElementsInRect
您的自定义UICollectionViewLayout
类的方法中完成的。
会自动调用此方法UICollectionViewController
。当UICollectionViewController
需要出现在屏幕上的单元格的布局信息时(例如,由于滚动或在首次加载时),您将从填充其中的缓存中返回属性prepareLayout
。
最后回答您的问题:在步骤2中,如何以及何时获得像元大小?
答:每个像元大小都是在prepareLayout
您的自定义方法中获得的UICollectionViewFlowLayout
,并且是在生命周期的早期计算出来的UICollectionView
。
在第3步中,我如何以及何时可以将更改通知布局?
请注意,本教程并未考虑要在运行时添加的新单元格:
注意:由于每当集合视图的布局无效时都会调用prepareLayout(),因此在典型的实现中,很多情况下您可能需要在此处重新计算属性。例如,UICollectionView的边界可能会发生变化(例如,方向发生变化时),或者可能会在集合中添加或删除项目。这些情况不在本教程的讨论范围之内,但是在非平凡的实现中意识到它们很重要。
就像他写的那样,这可能是您需要的一个微不足道的实现。但是,如果您的数据集很小(或出于测试目的),则可能会采用一种琐碎(非常低效)的实现。当由于屏幕旋转或添加/删除单元而需要使布局无效时,可以清除自定义中的缓存UICollectionViewFlowLayout
以强制prepareLayout
重新初始化布局属性。
例如,当您必须调用reloadData
collectionView时,还调用您的自定义布局类,以删除缓存:
cache.removeAll()