How to determine height of UICollectionView with FlowLayout
Solution 1
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.
Solution 2
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
Solution 3
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];
Solution 4
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
}
}
Solution 5
user1046037 answer in Swift...
class DynamicCollectionView: UICollectionView {
override func layoutSubviews() {
super.layoutSubviews()
if bounds.size != intrinsicContentSize() {
invalidateIntrinsicContentSize()
}
}
override func intrinsicContentSize() -> CGSize {
return self.contentSize
}
}
![Jan Z.](https://i.stack.imgur.com/sjYfD.jpg?s=256&g=1)
Jan Z.
Since I got to know OOP in school, I've been a coding enthusiast. Sometimes working on private projects, sometimes doing some web design and web development for social or sustainable projects as well as non-profits, I improved my skills over the time. I started with Delphi, moved on to C#, did some work with PHP, HTML, CSS and Javascript, and had a good start with Java and the Android API. After that, I worked on an iOS project for about a 3/4 year, learning much about Objective C and Cocoa, and especially CoreData. Currently I work as a developer at Zollsoft. Even though I feel at home in the FOSS Linux and unixoid world, I'm open to almost any platform. In the future I'd like to learn more about machine learning and data mining.
Updated on January 15, 2020Comments
-
Jan Z. over 4 years
I've got an
UICollectionView
with anUICollectionViewFlowLayout
, and i want to calculate its content size (for return inintrinsicContentSize
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 theUICollectionView
.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.
-
Chris Chen over 10 yearswhoa, I wish UITableView has something similar
-
Chris Conover about 10 yearsIgnatus, @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!
-
Georg over 9 yearsdidn'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 :(
-
rounak over 9 yearsWhat's the difference between collectionViewContentSize and contentSize of the scroll view?
-
dotToString about 9 yearsAwesome. Short and sweet solution to my UICollectionView inside of a UIScrollView!
-
thesummersign about 9 years@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 about 9 yearsOne important thing is to disable scrolling and scrollbars in the collection view
-
Jun over 8 yearsWhen you call contentSize of the collection view in viewDidLoad, it returns the frame of the collection view, collectionViewContentSize returns correct content size.
-
xtrinch about 8 yearsSame problem as Georg, it's about 50px in height when it should be more than 400
-
Maverick1st over 7 years@Georg i have exactly the same problem and haven't found a solution yet. Did you find one?
-
Georg over 7 yearsYes, 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 over 7 yearsIMHO 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.
-
DrMickeyLauer about 7 yearscollectionViewContentSize 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?
-
Abirami Bala about 7 yearsIm 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.....?
-
Sebastian about 7 yearsFor me calling
reloadData
before querying thecollectionViewContentSize
size helped. -
May Phyu almost 7 years@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 almost 7 years@May Phyu, Create outlet connection for UICollectionViewHeight and use following method. - (void)setCollectionViewHeight { self.collectionViewHeight.constant = self.collectionView.collectionViewLayout.collectionViewContentSize.height; } // Call this method after loading the data.
-
Mohammad Sadiq Shaikh over 6 yearsjust set this class to your collectionview in Storyboard
-
Er. Vihar over 6 years@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 over 6 yearsam getting this error : An -observeValueForKeyPath:ofObject:change:context: message was received but not handled.
-
Er. Vihar over 6 years@ShikhaSharma: Sorry, It's my mistake to specify the method. Try to put removeobserver code in viewWillDisappear.
-
Chen Li Yong almost 6 years@ChrisChen TableView actually does have something similar, and even more easier. Just call
myTableView.contentSize
and you'll get the content size asCGSize
! -
Rahul K Rajan over 5 yearsI found that its not working in iPhone 6/7 plus and XR,XS-MAX
-
Ajay Kumar over 5 yearsThis saved me, Thanks!
-
KolaCaine over 5 yearsIt's work perfectly but If you have something like
UILabel
above, the content fromcollectionView
pass over other element above, do you have another solution ? -
asanli about 5 yearsFor whom it can help: I had to do a "layoutIfNeeded()" before this so I could get it working.
-
ArielSD almost 5 yearsWhen is
collectionViewContentSize
set? When can we read from it? -
SinisterMJ almost 3 yearsJust made use of this and it worked pretty well - it had the advantage of informing my callback before the screen actually displayed to the user, so that I was able to adjust a critical constraint size based on the final size of the UICollectionView being rendered.