I currently have the following snippet for calculating UICollectionViewCells
sizes:
- (CGSize)collectionView:(UICollectionView *)mainCollectionView
layout:(UICollectionViewLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)atIndexPath
{
CGSize bounds = mainCollectionView.bounds.size;
bounds.height /= 4;
bounds.width /= 4;
return bounds;
}
This works. However, I'm now adding a keyboard observer in viewDidLoad
(which is triggering the the delegate and data source methods for the UICollectionView
before it appears and resizes itself from the storyboard). The bounds are thus wrong. I also would like to support rotation. What's a good way of handling these two edge cases and re-calculating the sizes if the UICollectionView
changes size?
invalidateLayout()Invalidates the current layout and triggers a layout update.
A layout object that organizes items into a grid with optional header and footer views for each section.
An abstract base class for generating layout information for a collection view.
A compositional layout is a type of collection view layout. It's designed to be composable, flexible, and fast, letting you build any kind of visual arrangement for your content by combining — or compositing — each smaller component into a full layout.
The solution for invalidating your layout when the bounds of the collection view changes is to override shouldInvalidateLayoutForBoundsChange:
and return YES
.
It's also stated in the documentation: https://developer.apple.com/documentation/uikit/uicollectionviewlayout/1617781-shouldinvalidatelayoutforboundsc
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
return YES;
}
This should cover rotation support as well. If it doesn't, implement viewWillTransitionToSize:withTransitionCoordinator:
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
[super viewWillTransitionToSize:size
withTransitionCoordinator:coordinator];
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context)
{
[self.collectionView.collectionViewLayout invalidateLayout];
}
completion:^(id<UIViewControllerTransitionCoordinatorContext> context)
{
}];
}
You should handle the case when the collection view size is changed. If you change the orientation or constraints, viewWillLayoutSubviews method will be triggered.
You should invalidate the current collection view layout. After the layout is invalidated by using invalidateLayout method, the UICollectionViewDelegateFlowLayout methods will be triggered.
Here's the example code:
- (void)viewWillLayoutSubviews { [super viewWillLayoutSubviews]; [mainCollectionView.collectionViewLayout invalidateLayout]; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With