Reputation: 49087
How am I supposed to set the height of the cells in UICollectionView equal to the height of whatever the collection view is? The code below doesn't work because the collection views height is not known at this point it seems since the auto layout is messing with the properties at this stage. It causes the cells height to be higher than the actual collection view.
I will add 300 in bounty to an answer that solves this!
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSize(width: 100, height: collectionView.frame.size.height)
}
2015-12-16 18:43:53.643 My-app[1055:434762] the behavior of the enter code hereUICollectionViewFlowLayout is not defined because: 2015-12-16 18:43:53.643 My-app[1055:434762] the item height must be less than the height of the UICollectionView minus the section insets top and bottom values, minus the content insets top and bottom values. 2015-12-16 18:43:53.643 My-app[1055:434762] Please check the values return by the delegate. 2015-12-16 18:43:53.644 My-app[1055:434762] The relevant UICollectionViewFlowLayout instance is , and it is attached to ; layer = ; contentOffset: {0, 0}; contentSize: {3087, 307}> collection view layout: . 2015-12-16 18:43:53.644 My-app[1055:434762] Make a symbolic breakpoint at UICollectionViewFlowLayoutBreakForInvalidSizes to catch this in the debugger.
Solution that works based on hannads suggestion. If there are better ways please let me know
Made a property with a property observer.
var myCollectionViewHeight: CGFloat = 0.0 {
didSet {
if myCollectionViewHeight != oldValue {
myCollectionView.collectionViewLayout.invalidateLayout()
myCollectionView.collectionViewLayout.prepareLayout()
}
}
}
Override this method (it is called multiple times)
override func viewDidLayoutSubviews() {
myCollectionViewHeight = myCollectionView.bounds.size.height
}
Then I have this in my delegate:
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSize(width: 100, height: myCollectionViewHeight)
}
Upvotes: 21
Views: 19173
Reputation: 1481
Keep "Estimated Size" to "Automatic" and add this to your UIViewController
to make sure the UICollectionView
layout get updated after the content view got rendered:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.recentAthletesCollectionView.collectionViewLayout.invalidateLayout()
}
Upvotes: 0
Reputation: 348
I solved this problem with this solution:
2. Change in storyboard "Inset from:" from Safe Area to Content Inset
Upvotes: 1
Reputation: 1
This problem can be easily solved by setting the collectionViewLayout itemSize property inside your viewdidload:
collectionViewLayout.itemSize = .init(width: 80, height: 80)
Upvotes: 0
Reputation: 2094
In my case, I have to set collectionViewLayout.estimatedItemSize
to an explicit value (which has its height <= collection view's height) instead of UICollectionViewFlowLayout.automaticSize
.
The UICollectionViewFlowLayout.automaticSize
results a default 50pt by 50pt cell size, which is higher than my collection view. In this case, UIKit refuses to do any layout work, despite that the actual cell size after self-sizing calculation will be smaller.
// horizontally scrollable collection view
private var viewHeight: CGFloat?
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
if viewHeight != view.bounds.height {
viewHeight = view.bounds.height
layout.estimatedItemSize = CGSize(width: 50, height: viewHeight!)
layout.invalidateLayout()
}
}
Upvotes: 2
Reputation: 12514
I had been struggling with this issue for over a week and finally found an answer that worked for my specific case. My issue was a result of 1) loading remote images in the UICollectionViewCell's image, and 2) having an estimated cell size that was larger than what I set manually on the sizeForItemAt of the collection view layout.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.bounds.width, height: collectionView.bounds.height)
}
I was able to solve by reducing the cell size on the storyboard to an amount lower than my cell's size, and I also set "Estimate Size" to "None" (this last part is probably enough)
Upvotes: 6
Reputation: 1492
In my case , I add collectionview to tableviewcell, and collectionview item height is equal to tableviewcell height. when change tableviewcellheiht, i get this warning. to solve this , try this code
if (@available(iOS 11.0, *)) {
_collectionView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
} else {
}
Upvotes: 0
Reputation: 10095
I had this issue because I had pinned my UICollectionView
to the bottom of a UITableViewCell
without giving the collectionView
a height.
After making a few network requests and then calling [self.tableView reloadData]
in the UIViewController
, I got the same error message in the log.
I managed to resolve it by breaking the bottom constraint and giving the UICollectionView
a fixed height.
Upvotes: 1
Reputation: 822
Here is how I would do it. First add a global variable in the view controller which will be used to store the height of the collection view. In the viewDidLayoutSubviews
method, set this variable to the height of the collectionView, and if it changed, call a method to invalidate the UICollectionView
layout
collectionView.collectionViewLayout.invalidateLayout()
Which will call the method to set sizes of the collectionView cells, and in that method, set the height of the cell to the global variable holding the height of the collectionView.
Note: currently on my mobile and did not test this code. I might have missed something.
Upvotes: 12
Reputation: 4583
I ran into this issue as well and i was able to solve it by subtracting the relevant sectionInsets
. Once you subtract the insets that aren't considered in the .size.height
property it accepts the height.
Inside sizeForItemAtIndexPath
you need to subtract the section inset dimensions...
let sectionInset = self.collectionView?.collectionViewLayout.sectionInset
let heightToSubtract = sectionInset!.top + sectionInset!.bottom
return CGSize(width: 100.0, height: (self.collectionView?.bounds.height)! - heightToSubtract)
NOTE: I am force unwrapping the optionals here but to be safe you might want to check them
Upvotes: 0
Reputation: 4337
You try set this code to your viewDidLoad
:
self.automaticallyAdjustsScrollViewInsets = false
Hope this help!
Upvotes: 11