Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UICollectionViewFlowLayout not invalidating right on orientation change

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

like image 323
xxtesaxx Avatar asked May 02 '13 15:05

xxtesaxx


2 Answers

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.

like image 57
Bob Wakefield Avatar answered Nov 06 '22 01:11

Bob Wakefield


I used a combination of the two answers here to do what we are all trying to do really is make a collection view look like a table view but not use UITableView and get items in a single column (most likely)

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];

    [self.collectionView.collectionViewLayout invalidateLayout];
}
like image 8
cynistersix Avatar answered Nov 06 '22 01:11

cynistersix