Aleksandar • Vacić

iOS bits and pieces

How to invalidate flow collection view layout on rotation

Say you want to have grid layout with cells always half the size of the screen’s width. You want to maintain that layout in both portrait and landscape. Since iOS 8 that can’t be easier, with the right incantations.

First, subclass UICollectionViewFlowLayout.

Then add the following method into it:

1
2
3
4
5
6
7
8
9
- (UICollectionViewLayoutInvalidationContext *)invalidationContextForBoundsChange:(CGRect)newBounds {

  UICollectionViewFlowLayoutInvalidationContext *context = (UICollectionViewFlowLayoutInvalidationContext *)[super invalidationContextForBoundsChange:newBounds];
  context.invalidateFlowLayoutDelegateMetrics = (
                                                 CGRectGetWidth(newBounds) != CGRectGetWidth(self.collectionView.bounds) ||
                                                 CGRectGetHeight(newBounds) != CGRectGetHeight(self.collectionView.bounds)
                                                 );
  return context;
}

The key here is casting returned context from super as UICollectionViewFlowLayoutInvalidationContext which allows you to toggle the invalidateFlowLayoutDelegateMetrics property. That will tell UIKit that it should re-query FlowLayout’s delegate for the sizes.

In the collection view controller, make sure it’s set to adopt UICollectionViewDelegateFlowLayout protocol and then add this delegate call:

1
2
3
4
5
6
- (CGSize)collectionView:(UICollectionView *)collectionView
                layout:(UICollectionViewFlowLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath {

  return CGSizeMake(floor(self.view.bounds.size.width/2.0), 88);
}

Done.