UICollectionViewFlowLayout not invalidating right on orientation change

xxtesaxx picture xxtesaxx · May 2, 2013 · Viewed 24.6k times · Source

i have a UICollectionView with a UICollectionViewFlowLayout. I also implement the UICollectionViewDelegateFlowLayout protocol.

In my datasource i have a bunch of UIViewControllers which respond to a custom protocol so i can ask for their size and some other stuff.

In in the FlowLayout delegate when it asks for the sizeForItemAtIndexPath:, i return the item size which i get from my protocol. The ViewControllers which implement my protocol return a different item size depending on the orientation.

Now if i change the device orientation from portrait to landscape theres no problem (Items are larger in landscape) but if i change it back, i get this warning:

    the item width must be less that the width of the UICollectionView minus the section insets left and right values.
    Please check the values return by the delegate.

It still works but i don't like it to get warnings so maybe you can tell me what i am doing wrong. Also there is another problem. If i don't tell my collectionViews collectionViewLayout to invalidate in willAnimateRotationToInterfaceOrientation: the sizeForItemAtIndexPath: is never called.

Hope you understand what i mean. If you need additional information let me know :)

Answer

Bob Wakefield picture Bob Wakefield · Nov 18, 2013

This answer is late, but the accepted answer didn't work for me. I sympathize with the OP in wanting a fire-and-forget UICollectionViewFlowLayout. I suggest that invalidating the layout in the view controller is in fact the best solution.

I wanted a single horizontal scrolling line of cells, centered in the view, in both portrait and landscape.

I subclassed UICollectionViewFlowLayout.

I overrode prepareLayout to recalculate the insets and then call [super prepareLayout].

I overrode the getter for collectionViewContentSize to make certain the content size was correct.

The layout didn't invalidate on its own even though the bounds were changing with the reorientation.

- (void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    // does the superclass do anything at this point?
    [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];

    // do whatever else you need before rotating toInterfaceOrientation

    // tell the layout to recalculate
    [self.collectionViewLayout invalidateLayout];
}

The UICollectionViewFlowLayout maintains the scroll position between orientations. The same cell will be centered only if it is square.