How to determine height of UICollectionView with FlowLayout

uicollectionview dynamic height swift 4
uicollectionview inside uitableviewcell dynamic height
size for item at indexpath collectionview
systemlayoutsizefitting uicollectionviewcell
ios change collectionview height
uicollectionviewcell scale
uitableviewcell uicollectionview dynamic height
custom uicollectionviewcell height

I've got an UICollectionView with an UICollectionViewFlowLayout, and i want to calculate its content size (for return in intrinsicContentSize needed for adjusting its height via AutoLayout).

The problems is: Even if I have a fixed and equal height for all cells, I don't know how many "rows"/lines I have in the UICollectionView. I also can't determine that count by the number of items in my data source, since the cells representing the data items vary in width, so does consequently the number of items I have in one line of the UICollectionView.

Since I couldn't find any hints on this topic in the official documentation and googling didn't bring me any further, any help and ideas would be appreciated very much.

Whoa! For some reason, after hours of research, I now found a pretty easy answer to my question: I was completely searching in the wrong place, digging through all the documentation I could find on UICollectionView.

The simple and easy solution lies in the underlying layout: Just call collectionViewContentSize on your myCollectionView.collectionViewLayout property and you get the height and width of the content as CGSize. It's as easy as that.

How to make height collection views dynamic in your iOS apps, Dynamically calculating the collectionView's height as per its contentSize is simply a 3 step process. 1. Subclass UICollectionView and override  A flow layout works with the collection view’s delegate object to determine the size of items, headers, and footers in each section and grid. That delegate object must conform to the UICollection View Delegate Flow Layout protocol. Use of the delegate allows you to adjust layout information dynamically.

In case you are using Auto layout, then you could create a subclass of UICollectionView

If you use the below the code then you don't have to specify any height constraints for the collection view as it would vary based on the contents of the collection view.

Given below 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

collectionViewContentSize, Returns the width and height of the collection view's contents. The collection view uses this information to configure its own content size for scrolling purposes. Providing an estimated cell size can improve the performance of the collection view when the cells adjust their size dynamically. Specifying an estimate value lets the collection view defer some of the calculations needed to determine the actual size of its content. Specifically, cells that are not onscreen are assumed to be the estimated height.

At viewDidAppear you can get it by:

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

Maybe when you reload data then need to calculate a new height with new data then you can get it by: add observer to listen when your CollectionView finished reload data at viewdidload:

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

Then add bellow function to get new height or do anything after collectionview finished reload:

- (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 don't forget to remove observer:

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

Dynamic Sizing for Horizontal UICollectionViews, Calculating the height of the sizing cell. Adjusting the itemSize of the collectionView's flowLayout, and height constraint on the collectionView  The height constraint on the UICollectionView itself. The itemSize property of the flowLayout is the actual size that you want the cell to be. For ours, we set the width to be our static width that we have been using all along, and the height as our calculated height.

user1046037 answer in Swift...

class DynamicCollectionView: UICollectionView {
    override func layoutSubviews() {
        super.layoutSubviews()
        if bounds.size != intrinsicContentSize() {
            invalidateIntrinsicContentSize()
        }
    }

    override func intrinsicContentSize() -> CGSize {
        return self.contentSize
    }
}

How to determine height of UICollectionView with FlowLayout, CGSizeEqualToSize(bounds.size, self.intrinsicContentSize) { self.​invalidateIntrinsicContentSize() } } override var intrinsicContentSize: CGSize  lazy var collectionView: UICollectionView = { let layout = UICollectionViewFlowLayout() layout.scrollDirection = .horizontal //Provide Width and Height According to your need let cellWidth = UIScreen.main.bounds.width / 10 let cellHeight = UIScreen.main.bounds.height / 10 layout.itemSize = CGSize(width: cellWidth, height: cellHeight) //You can

Swift 3 code for user1046037 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
    }

}

UICollectionView autosize height, In Interface Builder I initially set the size of the UICollectionView to a small value so that not Then, whenever I know the content has changed I update the value of the flowLayout = [[UICollectionViewFlowLayout alloc]init]; width is the previously calculated cellWidth with the padding between cells removed. Ask the delegate for the height of the photo, then calculate the frame height based on this height and the predefined cellPadding for the top and bottom. If there is no delegate set, use default cell height.

Dynamic Cell Sizing in UICollectionView, A cell whose width and height are fully determined by its constraints indicates to your flow layout that it should ask the collection view and its  UICollectionViewLayoutAttributes, collectionView != nil else { // should never happen return nil } // if the current frame, once stretched to the full row intersects the previous frame then they are on the same row if indexPath.item != 0, let previousFrame = layoutAttributesForItem(at: IndexPath(item: indexPath.item - 1, section: indexPath.section))?.frame, currentItemAttributes.frame.intersects(CGRect(x: -.infinity, y: previousFrame.origin.y, width: .infinity, height: previousFrame.size

[iOS] UICollectionViewCell custom heights with autolayout and , In newer versions of iOS (maybe 9?), you can do away with custom height calculation of collection view cells, and rely entirely on flow layout's estimatedItemSize  Good attempt. But this will not work if you use a sectionInset on the collectionViewLayout. To fix this, (1) calculate the available width by taking the cell width and subtracting flowLayout.sectionInset.left and flowLayout.sectionInset.right from it. (2) Where you calculate the cellWidth, replace 'view.frame.width' with the value calculated at (1).

Autosizing, Full-width UICollectionViewCells in Swift, Learn how UICollectionViewCells can automatically compute height in a UICollectionView. you display in your UICollectionView to automatically determine height. collectionViewLayout if let flowLayout = layout as? Questions: I’m trying to get self sizing UICollectionViewCells working with Auto Layout, but I can’t seem to get the cells to size themselves to the content. I’m having trouble understanding how the cell’s size is updated from the contents of what’s inside the cell’s contentView.

Comments
  • whoa, I wish UITableView has something similar
  • Ignatus, @jbandi, Chris et al, can you expand on this? When I tested with a horizontal scroll direction with a large inter-item spacing (so that the items would lay out horizontally), the collection view returned an invalid intrinsic content size (-1, -1), and collectionViewContentSize returned the what was effectively the bounds of the collection view - not taking into account that there was only one row surrounded by space. In short, it was not very intrinsic. Thanks!
  • What's the difference between collectionViewContentSize and contentSize of the scroll view?
  • When you call contentSize of the collection view in viewDidLoad, it returns the frame of the collection view, collectionViewContentSize returns correct content size.
  • For whom it can help: I had to do a "layoutIfNeeded()" before this so I could get it working.
  • didn't work for me... I am using my CollectionView inside a UITableViewCell and would like the tableview to grow in height as the collection view grows in height using iOS8 UITableViewAutomaticDimension But my collectionview stays small :(
  • Awesome. Short and sweet solution to my UICollectionView inside of a UIScrollView!
  • One important thing is to disable scrolling and scrollbars in the collection view
  • Same problem as Georg, it's about 50px in height when it should be more than 400
  • Yes, I set the collectionview to "not scrollabe, no scollbars" and then reload it then the content of the tableview is set. Also the collectionview is a subclass that returns it's content size as intrinsicContentSize. Hope that helps!
  • It's work perfectly but If you have something like UILabel above, the content from collectionView pass over other element above, do you have another solution ?
  • Im a fresher, and Im not sure about where and how to use this in my ViewController, Can you please make an edit with the answer.....?