UICollectionViewCell sized relative to its collection-view - ios

I have a (horizontal) collection-view, and I change its size via auto layout constraints. However, when the collection-view's size changes, the cell remains the same static size.
To demonstrate, here's the collection-view in the view debugger (I've labeled both the collectionview and one of its cells):
As you can see, the cell remains the original size and is now actually taller than its encasing collection-view.
So how can I constrain the cell to always fit within its collection-view?

If you want to resize your view you can use the following to reset the item size on rotation, this would go inside your view controller subclass.
This should be fairly efficent as it is only called when the size of the visible view controller changes.
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator;
{
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
[coordinator animateAlongsideTransition:({
^(id<UIViewControllerTransitionCoordinatorContext> context) {
UICollectionViewFlowLayout *layout = (id)self.collectionView.collectionViewLayout; {
CGFloat height = CGRectGetHeight(self.collectionView.bounds);
layout.itemSize = (CGSize) {
.width = height,
.height = height
};
}
[layout invalidateLayout];
};
}) completion:nil];
}
You should also check out these answers for some more solutions.

I solved this through setting the item's height and width equal to the collection-view's height. I do this in sizeForItemAtIndexPath:
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(collectionView.frame.size.height, collectionView.frame.size.height);
}
Because in my case the cell's need to be perfect squares, setting the cell's height and width to the height of the collection-view works perfectly.
Not that your class must implement the UICollectionViewDelegateFlowLayout protocol for this method to be exposed.

Related

How to get Storyboard to support dynamically sized cells in UICollectionView?

I have the following layout in my dynamically-sized Storyboard:
However, when running the application (depending on the orientation), cells look like the following:
This is to be expected, because the previous cells had static heights and widths.
However, I'd like the cells to resize dynamically based on the device width (height can remain static for this purpose). The CollectionView itself resizes properly, because it's pinned to its superview, so how can cells be overridden with auto-layout constraints (vs. the static cell sizes dictated from the UICollectionView).
The simplest way seems to be over-riding the cell size via the delegate within my main View Controller:
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
float cellWidth = (self.view.frame.size.width / 2) - 35;
float cellHeight = cellWidth * 190.0f / 270.0f;
return CGSizeMake(cellWidth, cellHeight);
}
I'd prefer to have as much display logic in the storyboard, but I suppose this is room for future improvement for Apple.
The cell sizes aren't determined by auto layout, they're set by the itemSize property of the layout object. If you only have one cell type, then you only need one cell in the collection view in IB. When your collection view is loaded, you can set that size in code, based on the width of the collection view. I've done it like this,
-(void)viewWillLayoutSubviews {
self.layout.itemSize = CGSizeMake(self.collectionView.bounds.size.width/2.5, 100);
}

Constraints not updated in UICollectionViewCell subclass on iOS7

I have a collection view based layout with different cell sizes depending on the content. A regular cell is 200x200 px, but if there is no content I display a cell with the same size as the collection view itself.
I use
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath
to calculate the correct size.
How ever, my subviews to the cell does not update its constraints. The cell is really simple, just a UILabel that should be centered within the cell superview. I have a horizontal and a vertical center constraint (also tried to pin each edge to the superview). The result is that the subviews gets the same size and position as entered in Interface Builder (Storyboard).
I've set background colors for both the cell and the label and can see that the cell gets the correct size, but the label does not.
The problem only exists in iOS7 and works as it should in iOS8.
Please help!
Thank you Stackover flow related questions pane! Found this thread and it solved my problem.
Auto Layout in UICollectionViewCell not working
I put this in my UICollectionViewCell subclass:
- (void)setBounds:(CGRect)bounds {
[super setBounds:bounds];
self.contentView.frame = bounds;
}
For me when this issues is coming on IOS9 with swift 2. I just called awakeFromNib() and set autoresizingMask in UICollectionViewCell.
My UICollectionViewCell looks like this-:
override func awakeFromNib() {
self.contentView.autoresizingMask = [UIViewAutoresizing.FlexibleWidth , UIViewAutoresizing.FlexibleHeight]
}

How to make UICollectionViewCell fit its subviews (using Auto Layout)

How can I change the size of a UICollectionViewCell based on the size of its subviews, using Auto Layout?
My UICollectionViewCells each only have one view in their contentView. This is a custom UIView subclass of mine that automatically resizes itself to fit all its subviews using Auto Layout. It also implements -intrinsicContentSize correctly. However the UICollectionView, or rather its layout, do not seem to care about this.
I am using a UICollectionViewFlowLayout, and tried:
Leaving the itemSize at its default value. This gives me cells with a size of 50 x 50.
Implementing the delegate method -collectionView:layout:sizeForItemAtIndexPath:. However, when this method gets called, the cells (obviously) have not appeared on screen yet, and have not been updated by the Auto Layout system.
Is there any way to change my cells' size based on their subviews using the standard Apple classes? Or do I have to implement my own UICollectionViewLayout subclass, or something else?
Have you tried this :
[self.view layoutIfNeeded];
[UIView animateWithDuration:0.5 animations:^{
constraintConstantForWidth.constant = subviews.size.width;
constraintConstantForHeight.constant = subviews.size.height;
[self.view layoutIfNeeded];
}];
and make the priority of the constraint (low = 250)
I think that this issue we can handle by the constraint constant replacement.
I used
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0) {
UIButton *button = (UIButton *)[cell viewWithTag:2];
CGRect frame = cell.frame;
frame.size.width = button.frame.size.width;
cell.frame = frame;
}
}
and was able to resize my cell based on the width of the button subview in a little test app.
Make sure that the tags on your subviews are greater than 0 because if you use 0, it just gives you back the contentView. Other than that, this should get you there
Try collectionView:layout:sizeForItemAtIndexPath:
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return self.view.frame.size;
}

UICollectionView Layout Issue

I am using UICollectionView using the flow layout.
I have made a custom UICollectionViewCell for the same.
But on running the project the console keeps on throwing this error-
The behavior of the UICollectionViewFlowLayout is not defined because:
the item height must be less that the height of the UICollectionView minus the section insets top and bottom values.
I have made sure that the size of the cell is correct
Has anyone been able to resolve this issue.
I found that, using storyboards, you have to go into the storyboard and click on the overall View Controller (the view should be highlighted in blue) and go to the Attributes Inspector (the fourth tab on the right side of the screen) and unchecking the "Under Top Bars", "Under Bottom Bars", and "Under Opaque Bars." This cleared up the issue for me, and it cleared it for my coworkers as well.
I've been having some issues when the using a collection view to present full screen view controllers.
Basically at run time, it'll ask for the size of the item and simply return the size of the collection view:
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return self.collectionView.frame.size;
}
I know this is a very late reply, but I have also experienced this.
Inside my view controller, let's call it MyViewController I have a UICollectionView that is using custom UICollectionViewCells. I'm implementing the method collectionView:layout:sizeForItemAtIndexPath where I am returning a item size that is dependent on the height of the UICollectionView.
MyViewController is made in a storyboard using autolayout to control the height of the UIViewController.
The cells look fine when in portrait mode, but did not when in landscape mode.
I solved my issues by invalidating the UICollectionViewLayout of my UICollectionView inside the viewWillLayoutSubviews method.
- (void)viewWillLayoutSubviews {
[self.myCollectionView.collectionViewLayout invalidateLayout];
}
Earlier I had tried to invalidate the layout inside willAnimateRotationToInterfaceOrientation:duration, but it didn't work. The reason for this is probably that the sizes for all the views are not calculated yet, so we have to wait until autolayout has finished its magic. I refer to this SO thread.
Update for Swift 4.0:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.myCollectionView.collectionViewLayout.invalidateLayout()
}
Had this issue myself a few times when trying to create collection views with fullscreen cells. My problem was caused by laying out for 4" screen in IB/Storyboard and specifying 320*568 for item size, but running in the simulator using 3.5" screen, which has a height of 480. The solution is to specify your item size in code with something like:
UICollectionViewFlowLayout *layout = (id) self.collectionView.collectionViewLayout;
layout.itemSize = self.collectionView.frame.size;
This ensures that the cell size is set correctly at runtime.
If you are using storyboards and auto layout, debugging this kind of problems is really hard...
I had similar problem when trying to display UICollectionViewCell fullscreen on iPhone.
Most of the time issue is with the size of the cell set in
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)
or directly on flowLayout.itemSize.
But... try:
Select the ViewController:
Then uncheck Extend Edges options:
And now try setting your auto layout constraints.
Good luck.
That fixed my problem:
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(self.collectionView.frame.size.width, self.collectionView.frame.size.height - 70);
}
U can see padding value from top and bottom on this screen:
Be sure to set the right autoresizing mask for UICollectionView and UICollectionviewcell.
This fixed my problem for iPhone 4 Simulator
For me I am using AKPickerView inside of a custom UIView which was giving me a slew of warnings like the ones mentioned here. All I did to eliminate the warnings was to Un-Check the box called 'AutoResize Subviews' in the Attributes Inspector for my custom UIView. That silenced the warnings so hard, I thought my logger stopped working.
What caused this for me was that I was trying to set my cells to the size of the superview rather than the size of the UICollectionView. Simply replaced the superview frame with the UICollectionView frame.
I had this problem when I was need full screen cells in collectionView. So I resolved it with this decision.
Cell size is equal collection view size
2. Change in storyboard "Inset from:" from Safe Area to Content Inset
Change "Content Insets" to Never
I just ran into the same error message, but for me the issue was that when I received new data from the api and tried to refresh my collectionView, the method that called [collectionView reloadData] wasn't calling it on the main thread.
Hope this helps someone...
I have same issue
the behavior of the UICollectionViewFlowLayout is not defined because:
the item height must be less than the height of the UICollectionView minus the section insets top and bottom values.
I solved this issue by checking the values in section Insets.And for fix cell size I have used below code.
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
CGSize result = [[UIScreen mainScreen] bounds].size;
CGFloat scale = [UIScreen mainScreen].scale;
result = CGSizeMake(result.width * scale, result.height * scale);
CGFloat cellWidth = [[UIScreen mainScreen] bounds].size.width - 20;
CGFloat cellHeight = [[UIScreen mainScreen] bounds].size.height - 120;
return CGSizeMake(cellWidth, cellHeight);
}
If you're loading a collectionView via a container view + UICollectionViewController, you may have set a height constraint on the container view which is constraining the height of the collection view itself. In my case, I found the collectionView.contentSize was taller than the constraint I had set on my container view.
Obviously this is a bit of an edge case but just in case you have a similar setup, I figured I'd add this comment.
For me the solution was to set Estimate Size (in the storyboard size attributes pane) for the collection view to None.
It's complaining that the item height is bigger than the height of the collectionView. So it's sticking out.
So you have to make the height the same or less.
Like this:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.height, height: collectionView.frame.height)
}
Using the height for the width makes it a square. This is assuming inset is 0 which it should be if you haven't done anything.
None of the above fixes did it for me.
I fixed it with this
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{CGFloat currentWidth = collectionView.frame.size.width;
UIEdgeInsets sectionInset = [(UICollectionViewFlowLayout *)collectionView.collectionViewLayout sectionInset]; //here the sectionInsets are always = 0 because of a timing issue so you need to force set width of an item a few pixels less than the width of the collectionView.
CGFloat width = currentWidth - 10;
}

UICollectionViewFlowLayout Size Warning When Rotating Device to Landscape

We are using a UICollectionView to display cell that cover the full screen (minus the status and nav bar). The cell size is set from self.collectionView.bounds.size:
- (void)viewWillAppear:(BOOL)animated
{
//
// value isn't correct with the top bars until here
//
CGSize tmpSize = self.collectionView.bounds.size;
_currentCellSize = CGSizeMake( (tmpSize.width), (tmpSize.height));
}
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return _currentCellSize;
}
This sets the correct sizing for each device. Each cell is defined to have no insets, and the layout has no header or footer. However, when we rotate from portrait to landscape we get the following "complaint":
the behavior of the UICollectionViewFlowLayout is not defined because:
the item height must be less that the height of the UICollectionView minus the section insets top and bottom values.
Now I understand this error, however we reset the size of the cell and use the flow layouts built in rotation transition:
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
//self.collectionView.bounds are still the last size...not the new size here
}
- (void)didRotateFromInterfaceOrientation: UIInterfaceOrientation)fromInterfaceOrientation
{
CGSize tmpSize = self.collectionView.bounds.size;
_currentCellSize = CGSizeMake( (tmpSize.width), (tmpSize.height));
[self.collectionView performBatchUpdates:nil completion:nil];//this will force the redraw/size of the cells.
}
The cells render correctly in landscape.
It seems as though the Flow Layout sees the old cell size (which causes the complaint since it will be too tall), but does read/render the new cell size set in didRotateFromInterfaceOrientation.
Is there a way to get rid of the complaint?
We've tried finding another hook during a device rotate transition that has access to the correct target screen size (vs the current screen size) with no luck. Debug output shows the complaint happens after willRotateToInterfaceOrientation but before didRotateFromInterfaceOrientation.
We've also verified the obvious; if we set up the cell height to be a fixed size less than the landscape screen height, the complaint doesn't occur. Also, the complaint does not occur when rotating from landscape back to portrait.
Everything runs fine, and renders correctly. However this complaint worries us. Anyone else have any ideas or solutions?
I was getting the same warning. Unsatisfied with the "reloadData" approach, I found that calling [self.collectionView.collectionViewFlowLayout invalidateLayout] before setting the frame of the collection view silenced the warning and yielded the expected results.
Not to throw another shrimp on this loaded, yet unaccepted, barbie.
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
[collectionView setContentInset:UIEdgeInsetsMake(0, 0, 0, 0)];
return CGSizeMake(100, collectionView.frame.size.height);
}
Setting the content insets just before returning the cell size did the trick for me.
Note:
I am using a container view in a storyboard to load the collection view within a UIViewController. I tried setting this on the flowLayout object in the storyboard. The collection view in the storyboard. And overriding one of the UICollectionViewDelegateFlowLayout; though I do not remember which one. I'm also not sure if this will work for a vertical layout.
In
[UIViewController willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration]
I called the, [UICollectionViewLayout invalidateLayout] and seems to work good.
I solved it.
You should just let the height of flowLayout less than collcetionView.frame.size.height.
[flowLayout setItemSize:CGSizeMake(width, height)];
collectionView.frame = CGRectMake(12, 380, 290, 80);
A lot of the solutions suggest adding invalidateLayout to willAnimateRotationToInterfaceOrientation - but this is deprecated since iOS 8.
For iOS 8 and higher, use:
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
[self.collectionView.collectionViewLayout invalidateLayout];
}
Thanks to #user7097242's comment here is a swift4 version:
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
self.collectionView.collectionViewLayout.invalidateLayout()
}
I encountered this same issue. If the collection view was displayed when in portrait orientation, the cells would disappear when rotated to landscape. I did a combination of the other answers here to fix this.
I set my view (the one that contains the UICollectionView) up to receive the UIDeviceOrientationDidChangeNotification notification. In the method that responds to that notification, after the UICollectionView frame was adjusted, I did the following:
- (void)orientationChanged:(NSNotification *)notification
{
CGSize size = (CGSize){self.frame.size.width - 2*kContentMargin, self.frame.size.height - 2*kContentMargin};
[self.collectionView.collectionViewLayout setItemSize:size];
[self.collectionView.collectionViewLayout invalidateLayout];
[self.collectionView reloadData];
}
Note that the frame of the UICollectionView is being set automatically upon rotation because its resizingMask is set to this upon initialization:
self.collectionView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
Just encountered and fixed the same problem. Since my solution is more along the lines you were asking for and doesn't match any existing answer, I've posted it here.
#define NUMBER_OF_CELLS_PER_ROW 1
- (UICollectionViewFlowLayout *)flowLayout {
return (UICollectionViewFlowLayout *)self.collectionViewLayout;
}
- (CGSize)itemSizeInCurrentOrientation {
CGFloat windowWidth = self.collectionView.window.bounds.size.width;
CGFloat width = (windowWidth - (self.flowLayout.minimumInteritemSpacing * (NUMBER_OF_CELLS_PER_ROW - 1)) - self.flowLayout.sectionInset.left - self.flowLayout.sectionInset.right)/NUMBER_OF_CELLS_PER_ROW;
CGFloat height = 80.0f;
return CGSizeMake(width, height);
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
[self.flowLayout invalidateLayout];
self.flowLayout.itemSize = [self itemSizeInCurrentOrientation];
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
// Now that the rotation is complete, load the cells.
[self.collectionView reloadData];
}
This solved it for me:
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
[self.collectionView.collectionViewLayout invalidateLayout];
}
And I am using this delegate method for setting the size:
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
And I can from there use this with the correct frame after rotation:
self.collectionView.frame.size
My fix was as simple as unchecking 'Adjust Scroll View Insets' for the view controller in IB, since I needed my navigation bar to be translucent.
This works for me: (and hope it also works for you!)
- (void)viewWillLayoutSubviews
{
self.flowLayout.itemSize = CGSizeMake(self.collectionView.bounds.size.width/4,self.collectionView.bounds.size.height);
[self.flowLayout invalidateLayout];
}
- (void)viewDidLayoutSubviews
{
self.flowLayout.itemSize = CGSizeMake(self.collectionView.bounds.size.width/4,self.collectionView.bounds.size.height);
}
I faced the same problem.
here is how i solved it. hope it helps
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:( NSTimeInterval)duration
{
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
[self.collectionView reloadData];
}
I ran into the same problem when resizing the frame of a UICollectionView. If I used the delegate method on FlowLayout to return the size of the cell (which would be updated based on the size of the containing UICollectionView), I would get the error message when I resized (smaller) the frame of the UICollectionView, since it didn't seem to ask the delegate for updated size information before complaining. It would eventually ask the delegate method for size info when redrawing, but it would still issue the warning at the time I assigned a new frame method. To get rid of the warning, I explicitly set the itemSize property of the UICollectionViewFlowLayout object before I set the frame to a new smaller value. My situation is simple enough that I think I can get away with doing the itemSize calculation at this point (since all my items in the collection view are the same size), instead of depending on the delegate method. Just setting the itemSize property while leaving the delegate method implemented did not solve the problem, as I think it ignored the value of itemSize if it detected that the delegate method was implemented (if it knows it is there, why doesn't it call it?!). Hopefully this helps - perhaps you can also explicitly set the itemSize before rotation.
Just to suppress warning and (probably, not sure) improve performance you could before returning size in
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
check if view controller is in process of rotation and if it is return some relatively small size like CGSizeMake(0.1, 0.1)
You can subclass UICollectionView and override setBounds:. There before calling [super setBounds:] the item size can be adjusted to the new bounds.
You should check whether the size of the bounds has changed, because setBounds: is invoked also while scrolling.
Try this...
UICollectionViewFlowLayout *layout = (id) self.collectionView.collectionViewLayout;
layout.itemSize = CGSizeMake(0.1, 0.1);
It's works for me.
Following code fixed it for me:
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return self.collectionView.frame.size;
}
I've used an UICollectionViewFlowLayoutInvalidationContext, in which I calculate the new offset such that it maintains the same content offset. My own function collectionViewSizeForOrientation: returns the proper size. Its not perfect, but at least it's not sketchy:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
CGSize fromCollectionViewSize = [self collectionViewSizeForOrientation:[self interfaceOrientation]];
CGSize toCollectionViewSize = [self collectionViewSizeForOrientation:toInterfaceOrientation];
CGFloat currentPage = [_collectionView contentOffset].x / [_collectionView bounds].size.width;
NSInteger itemCount = [_collectionView numberOfItemsInSection:0];
UICollectionViewFlowLayoutInvalidationContext *invalidationContext = [[UICollectionViewFlowLayoutInvalidationContext alloc] init];
[invalidationContext setContentSizeAdjustment:CGSizeMake(toCollectionViewSize.width * itemCount - fromCollectionViewSize.width * itemCount, toCollectionViewSize.height - fromCollectionViewSize.height)];
[invalidationContext setContentOffsetAdjustment:CGPointMake(currentPage * toCollectionViewSize.width - [_collectionView contentOffset].x, 0)];
[[_collectionView collectionViewLayout] invalidateLayoutWithContext:invalidationContext];
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
}
collectionViewSizeForOrientation: in my case is the following, assuming that insets and item spacing are 0:
- (CGSize)collectionViewSizeForOrientation:(UIInterfaceOrientation)orientation
{
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
CGFloat width = UIInterfaceOrientationIsLandscape(orientation) ? MAX(screenSize.width, screenSize.height) : MIN(screenSize.width, screenSize.height);
CGFloat height = UIInterfaceOrientationIsLandscape(orientation) ? MIN(screenSize.width, screenSize.height) : MAX(screenSize.width, screenSize.height);
return CGSizeMake(width, height);
}
Trying to find a solution to silence these warnings on iOS 7 was proving difficult for me. I ended up resorting to subclassing my UICollectionView and added the following code.
- (void)setFrame:(CGRect)frame
{
if (!iOS8 && (frame.size.width != self.frame.size.width))
{
[self.collectionViewLayout invalidateLayout];
}
[super setFrame:frame];
}
Some might want to do a whole size check with CGSizeEqualToSize().
try at the end of didRotateFromInterfaceOrientation:
[self.collectionView setNeedsLayout]
if it does not work try to move all this stuff from didRotateFromInterfaceOrientation to willRotateToInterfaceOrientation
Note: In my case, I discovered that we were setting the preferredContentSize property of the UIViewController in question. If you find this to be your case, you might have to deal with the following method of the UICollectionViewDelegateFlowLayout protocol:
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
CGSize size = collectionViewLayout.collectionView.bounds.size;
...
return size;
}
I know this is an old question, but I just got the same problem and spent an hour to solve it. My problem was that, it seems the UICollectionView's frame size is always wrong (the height doesn't match the container) while I set the frame size right before the UICollectionView Flow layout delegate is called. So, I set the UICollectionView frame size again on the method :
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
And that did the trick. The height is now showing correctly and the warning is gone.

Resources