How to determine the height of a UICollectionView with FlowLayout

I have a UICollectionView with a UICollectionViewFlowLayout , and I want to calculate its content size (to return to intrinsicContentSize needed to adjust its height using AutoLayout).

Problems: Even if I have a fixed and equal height for all cells, I don’t know how many β€œrows” / rows I have in the UICollectionView . I also cannot determine this count by the number of elements in my data source, since the cells representing the data elements differ in width, so the number of elements that I have is on the same UICollectionView line.

Since I could not find any hints on this topic in the official documentation, and googling did not lead me further, any help and ideas would be greatly appreciated.

+107
ios height autolayout uicollectionview
Dec 09
source share
11 answers

Wow! For some reason, after several hours of research, I found a fairly simple answer to my question: I was completely looking for the wrong place, breaking through all the documentation that I could find on the UICollectionView .

A simple and simple solution lies in the basic layout: just call collectionViewContentSize your property myCollectionView.collectionViewLayout and you will get the height and width of the content as CGSize . It is so simple.

+238
Dec 09
source share

If you use AutoClass , you can subclass UICollectionView

If you use the code below, you do not need to specify any height restrictions for the collection view, as this depends on the contents of the collection view.

The following is the implementation:

 @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 
+34
07 Oct '14 at 8:53
source share

In viewDidAppear you can get it:

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

Perhaps when you reload the data, you need to calculate the new height with the new data, then you can get it: add an observer to listen when your CollectionView finished reloading the data in viewdidload :

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

Then add the following function to get a new height or do something after the collection has finished loading:

 - (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; } 

And do not forget to remove the observer:

 [self.myCollectionView removeObserver:self forKeyPath:@"contentSize" context:NULL]; 
+19
07 Feb '15 at 4:40
source share

user1046037 answer in Swift ...

 class DynamicCollectionView: UICollectionView { override func layoutSubviews() { super.layoutSubviews() if bounds.size != intrinsicContentSize() { invalidateIntrinsicContentSize() } } override func intrinsicContentSize() -> CGSize { return self.contentSize } } 
+11
Apr 20 '16 at 15:09
source share

Swift 3 for user 1046037 answer

 import UIKit class DynamicCollectionView: UICollectionView { override func layoutSubviews() { super.layoutSubviews() if !__CGSizeEqualToSize(bounds.size, self.intrinsicContentSize) { self.invalidateIntrinsicContentSize() } } override var intrinsicContentSize: CGSize { return contentSize } } 
+8
Nov 06 '16 at 6:33
source share

Too late to answer this question, but I recently survived this question.
@lee above answer help me a lot to get my answer. But this answer is limited to objective-c , and I worked in quickly .
@lee Regarding your answer, let me let a fast user solve this problem easily. To do this, follow these steps:

Declare a CGFloat variable in the declaration section:

 var height : CGFloat! 

In viewDidAppear you can get it:

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

Maybe when you reload data, then you need to calculate the new height with the new data, then you can get it: addObserver to listen when your CollectionView finished reloading the data in viewWillAppear :

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

Then add the following function to get a new height or to do something after CollectionView reboot is completed:

 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 } 

And do not forget to remove the observer:

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

I hope this helps you quickly solve your problem.

+3
Apr 19 '17 at 5:38 on
source share

Swift 4

 class DynamicCollectionView: UICollectionView { override func layoutSubviews() { super.layoutSubviews() if !__CGSizeEqualToSize(bounds.size, self.intrinsicContentSize) { self.invalidateIntrinsicContentSize() } } override var intrinsicContentSize: CGSize { return collectionViewLayout.collectionViewContentSize } } 
+3
Mar 23 '18 at 3:01
source share

Swift 4.2

 class DynamicCollectionView: UICollectionView { override func layoutSubviews() { super.layoutSubviews() if bounds.size != intrinsicContentSize { invalidateIntrinsicContentSize() } } override var intrinsicContentSize: CGSize { return self.contentSize } } 
+1
Jan 09 '19 at 17:43
source share

Swift version @ user1046037:

 public class DynamicCollectionView: UICollectionView { override public func layoutSubviews() { super.layoutSubviews() if !bounds.size.equalTo(intrinsicContentSize) { invalidateIntrinsicContentSize() } } override public var intrinsicContentSize: CGSize { let intrinsicContentSize: CGSize = contentSize return intrinsicContentSize } } 
0
Mar 01 '18 at 17:28
source share

In addition: before calling reloadData it is better to call reloadData : myCollectionView.collectionViewLayout.collectionViewContentSize

0
Oct 29 '18 at 3:25
source share

Swift 4.2, Xcode 10.1, iOS 12.1:

For some reason, collectionView.contentSize.height looked less than the allowed height of my collection view. Firstly, I used the auto-layout restriction with respect to 1/2 the height of the superview. To fix this, I changed the restriction to a "safe area" view.

This allowed me to set the cell height to populate the view of my collection using collectionView.contentSize.height :

 private func setCellSize() { let height: CGFloat = (collectionView.contentSize.height) / CGFloat(numberOfRows) let width: CGFloat = view.frame.width - CGFloat(horizontalCellMargin * 2) let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout layout.itemSize = CGSize(width: width, height: height) } 

Before

height constraint relative to superview bad simulator result

After

height constraint relative to safe area good simulator result

0
May 6 '19 at 17:54
source share



All Articles