I'm implementing a collection view whose items are sized based on the bounds of the collection view. Therefore when the size changes, due to rotating the device for example, I need to invalidate the layout so that the cells are resized to consider the new collection view bounds. I have done this via the viewWillTransitionToSize
API.
This works well until the user presents a modal view controller over the view controller that contains the collection view, rotates the device, then dismisses it. When that occurs the item size hasn't updated to the appropriate size. viewWillTransitionToSize
is called and the layout is invalidated as expected, but the collection view's bounds is still the old value. For example when rotating from portrait to landscape the collection view bounds value still has its height greater than the width. I'm not sure why that's the case, but I'm wondering if this is the best way to invalidate upon size change? Is there a better way to do it?
I have also tried subclassing UICollectionViewFlowLayout
and overriding shouldInvalidateLayoutForBoundsChange
to return YES
, but for some reason this doesn't work even rotating without a modal presentation. It doesn't use the proper collection view bounds either.
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(nonnull id<UIViewControllerTransitionCoordinator>)coordinator
{
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
[self.collectionView.collectionViewLayout invalidateLayout];
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> __nonnull context) {
[self.collectionView.collectionViewLayout invalidateLayout];
} completion:^(id<UIViewControllerTransitionCoordinatorContext> __nonnull context) {
//finished
}];
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewFlowLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
//collectionView.bounds.size is not always correct here after invalidating layout as explained above
}
I've also tried invaliding it in the completion block but it still doesn't use the proper collection view bounds.
If I invalidate the layout again in viewWillAppear
, this does use the proper collection view bounds which resolves the issue with rotating with the modally presented view controller. But this shouldn't be necessary, perhaps there are other situations where this won't be sized properly.