如何用FlowLayout确定UICollectionView的高度

我有一个UICollectionViewUICollectionViewFlowLayout ,我想计算其内容大小(为了通过AutoLayout调整其高度所需的intrinsicContentSize返回)。

问题是:即使我对所有的单元格有一个固定和相等的高度,我不知道在UICollectionView有多less“行”/行。 我也不能通过数据源中的项目数来确定计数,因为表示数据项的单元格的宽度是不同的,所以我在UICollectionView一行中有多less个项目。

由于在官方文档中我找不到任何关于这个主题的提示,并且Google的search引擎没有给我带来更多的帮助,所以任何帮助和想法都非常值得赞赏。

哇! 出于某种原因,经过几个小时的研究,我现在发现了一个非常简单的答案:我完全在错误的地方search,挖掘了我在UICollectionViewfind的所有文档。

简单而简单的解决scheme在于底层布局:只需在myCollectionView.collectionViewLayout属性上调用collectionViewContentSize ,并以CGSize的forms获取内容的高度和宽度。 就这么简单

如果你使用自动布局 ,那么你可以创build一个UICollectionView的子类

如果使用下面的代码,那么您不必为集合视图指定任何高度约束,因为它会根据集合视图的内容而有所不同。

下面给出的是实现:

 @interface DynamicCollectionView : UICollectionView @end @implementation DynamicCollectionView - (void) layoutSubviews { [super layoutSubviews]; if (!CGSizeEqualToSize(self.bounds.size, [self intrinsicContentSize])) { [self invalidateIntrinsicContentSize]; } } - (CGSize)intrinsicContentSize { CGSize intrinsicContentSize = self.contentSize; return intrinsicContentSize; } @end 

viewDidAppear你可以得到它:

 float height = self.myCollectionView.collectionViewLayout.collectionViewContentSize.height; 

也许当你重新加载数据,然后需要用新的数据计算一个新的高度,那么你可以得到它:添加观察者来监听什么时候你的CollectionView完成在viewdidload重新加载数据:

 [self.myCollectionView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionOld context:NULL]; 

然后添加bellow函数来获取新的高度,或者在collectionview完成重载之后执行任何操作:

 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { //Whatever you do here when the reloadData finished float newHeight = self.myCollectionView.collectionViewLayout.collectionViewContentSize.height; } 

不要忘记删除观察者:

 [self.myCollectionView removeObserver:self forKeyPath:@"contentSize" context:NULL]; 

user1046037在Swift中回答…

 class DynamicCollectionView: UICollectionView { override func layoutSubviews() { super.layoutSubviews() if bounds.size != intrinsicContentSize() { invalidateIntrinsicContentSize() } } override func intrinsicContentSize() -> CGSize { return self.contentSize } } 

Swift 3代码为user1046037答案

 import UIKit class DynamicCollectionView: UICollectionView { override func layoutSubviews() { super.layoutSubviews() if !__CGSizeEqualToSize(bounds.size, self.intrinsicContentSize) { self.invalidateIntrinsicContentSize() } } override var intrinsicContentSize: CGSize { return contentSize } } 

回答这个问题为时已晚,但最近我经历了这个问题。
@李的上面的答案帮助我很多得到我的答案。 但是,这个答案仅限于Objective-C ,我正在迅速工作。
@lee参考你的答案,让我让迅速的用户很容易解决这个问题。 为此,请按以下步骤操作:

在声明部分声明一个CGFloatvariables:

 var height : CGFloat! 

viewDidAppear你可以得到它:

 height = self.myCollectionView.collectionViewLayout.collectionViewContentSize().height 

也许当你reload数据,然后需要用新的数据计算一个新的高度,那么你可以得到它: addObserver来监听你的CollectionView完成重新加载数据在viewWillAppear

 override func viewWillAppear(animated: Bool) { super.viewWillAppear(true) .... .... self.shapeCollectionView.addObserver(self, forKeyPath: "contentSize", options: NSKeyValueObservingOptions.Old, context: nil) } 

然后添加bellow函数来获取新的高度,或者在collectionview完成重载之后执行任何操作:

 override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) { let newHeight : CGFloat = self.myCollectionView.collectionViewLayout.collectionViewContentSize().height var frame : CGRect! = self.myCollectionView.frame frame.size.height = newHeight self.myCollectionView.frame = frame } 

不要忘记删除观察者:

 override func viewWillDisappear(animated: Bool) { super.viewWillDisappear(true) .... .... self.myCollectionView.removeObserver(self, forKeyPath: "contentSize") } 

我希望这会帮助你迅速解决你的问题。