By Ignatius Tremor


2012-12-09 14:54:26 8 Comments

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.

10 comments

@Cesare 2019-01-09 17:43:57

Swift 4.2

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

    override var intrinsicContentSize: CGSize {
        return self.contentSize
    }
}

@guozqzzu 2018-10-29 03:25:07

In addition : You'd better calling reloadData before getting the height through :myCollectionView.collectionViewLayout.collectionViewContentSize

@Wilson 2018-03-23 03:01:15

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

@Rahul K Rajan 2018-10-17 12:50:00

I found that its not working in iPhone 6/7 plus and XR,XS-MAX

@Joshua Hart 2018-03-01 17:28:11

Swift version of @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
    }
}

@Er. Vihar 2017-04-19 05:38:30

It's too late to answer this question but I have recently gone through this issue.
@lee's above answer help me a lot to get my answer. But that answer is limited to objective-c and I was working in swift.
@lee With reference to your answer, allow me to let the swift user get this issue solved easily. For that, please follow below steps:

Declare a CGFloat variable in declaration section:

var height : CGFloat!

At viewDidAppear you can get it by:

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: addObserver to listen when your CollectionView finished reload data at viewWillAppear:

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

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

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

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

I hope this will help you to solve your issue in swift.

@Shikha Sharma 2017-11-06 12:35:34

where to put removeobserver code ?

@Er. Vihar 2017-11-06 12:47:06

@ShikhaSharma: You can add the removeObserver code within "ViewDidDisappear" method, which will remove observer only after the view confirms that its disappeared. Please check the updated answer.

@Shikha Sharma 2017-11-06 12:52:30

am getting this error : An -observeValueForKeyPath:ofObject:change:context: message was received but not handled.

@Er. Vihar 2017-11-06 13:15:24

@ShikhaSharma: Sorry, It's my mistake to specify the method. Try to put removeobserver code in viewWillDisappear.

@Mohammad Sadiq Shaikh 2016-11-06 06:33:10

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
    }

}

@Abirami Bala 2017-05-16 06:58:12

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.....?

@Mohammad Sadiq Shaikh 2017-11-01 06:37:12

just set this class to your collectionview in Storyboard

@Nick Wood 2016-04-20 15:09:34

user1046037 answer in Swift...

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

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

@KolaCaine 2019-02-18 18:58:22

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 ?

@lee 2015-02-07 04:40:53

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];

@user1046037 2014-10-07 08:53:47

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

@Georg 2014-11-11 13:28:43

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 :(

@dotToString 2015-05-30 00:50:50

Awesome. Short and sweet solution to my UICollectionView inside of a UIScrollView!

@thesummersign 2015-06-18 07:17:39

@Georg, I am trying to do something similar. But when there is a deadlock. The collection view will get its layout information after cell loads on View and the cell loads after the height is calculated but the height need to be calculated from the collectionview. How did you fix this?

@Georg 2015-06-18 13:07:47

One important thing is to disable scrolling and scrollbars in the collection view

@xtrinch 2016-06-08 13:40:41

Same problem as Georg, it's about 50px in height when it should be more than 400

@Khant Thu Linn 2016-12-08 03:43:33

@Georg do you have solution for your case already?

@Maverick1st 2017-02-24 13:19:13

@Georg i have exactly the same problem and haven't found a solution yet. Did you find one?

@Georg 2017-02-24 18:55:03

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!

@user1046037 2017-02-25 00:52:23

IMHO it might be better to use the collection view without using the table view. If the flow layout doesn't meet your requirement you could create your own custom layout.

@Ignatius Tremor 2012-12-09 15:09:55

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.

@Chris Chen 2014-02-26 00:27:51

whoa, I wish UITableView has something similar

@Chris Conover 2014-05-15 00:28:33

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!

@rounak 2015-01-06 16:59:04

What's the difference between collectionViewContentSize and contentSize of the scroll view?

@Egor T 2016-03-10 12:40:46

When you call contentSize of the collection view in viewDidLoad, it returns the frame of the collection view, collectionViewContentSize returns correct content size.

@DrMickeyLauer 2017-04-06 13:57:45

collectionViewContentSize only works on the 2nd (sometimes also 3rd) time for me, the first time it always returns a too large width (I have pinned the width, but care for a variable height), thus I have to force relayout at least once. Is there a better way?

@Sebastian 2017-06-15 11:39:06

For me calling reloadData before querying the collectionViewContentSize size helped.

@May Phyu 2017-09-05 04:30:11

@MananDevani, could you please share your code or tutorial relating to this problem?. I have got such a problem right now. I don't know how to solve it. :(

@Manan Devani 2017-09-07 08:01:12

@May Phyu, Create outlet connection for UICollectionViewHeight and use following method. - (void)setCollectionViewHeight { self.collectionViewHeight.constant = self.collectionView.collectionViewLayout.collectionViewConte‌​ntSize.height; } // Call this method after loading the data.

@Chen Li Yong 2018-07-02 07:55:44

@ChrisChen TableView actually does have something similar, and even more easier. Just call myTableView.contentSize and you'll get the content size as CGSize!

@Ajay Kumar 2018-12-23 21:46:08

This saved me, Thanks!

@asanli 2019-04-05 16:58:23

For whom it can help: I had to do a "layoutIfNeeded()" before this so I could get it working.

Related Questions

Sponsored Content

22 Answered Questions

[SOLVED] Make body have 100% of the browser height

  • 2011-07-11 18:50:56
  • bodyofheat
  • 752316 View
  • 715 Score
  • 22 Answer
  • Tags:   html css height

26 Answered Questions

31 Answered Questions

[SOLVED] How to make a div 100% height of the browser window?

  • 2009-10-15 21:18:43
  • mike
  • 1717223 View
  • 1885 Score
  • 31 Answer
  • Tags:   html css css3 height

13 Answered Questions

[SOLVED] How do I animate constraint changes?

0 Answered Questions

UICollectionView in a UItableViewCell, grid-view layout

1 Answered Questions

2 Answered Questions

1 Answered Questions

[SOLVED] Auto height UICollectionView

1 Answered Questions

UICollectionView loaded from Storyboard is NOT resizing correctly

  • 2015-02-02 05:33:52
  • debuggenius
  • 159 View
  • 1 Score
  • 1 Answer
  • Tags:   ios autolayout

1 Answered Questions

[SOLVED] UICollectionView with cells wrapping content

Sponsored Content