We commonly use Collection view where its cell size calculated run time. The flow layout delegate is responsible to return individual cell sizes. BUT in most of the cases, delegate method `collectionView: layout sizeForItem:` expects cell size too early. Before generating actual cell size.
You can find similar queries in StackOverflow community :
We know `viewWillLayoutSubviews` is responsible for all frame layout calculations in a view controller. At same point, we will have freshly calculated frame ready to be used. Thus, invalidating collection view layout after update will redraw its cell right after external view layout gets updated. Apparently, `invalidateLayout()` will call again flow layout delegate `collectionView: layout sizeForItem:`
extension YourViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: externalWidth, height: externalHeight)
}
}
For instance, if a cell size depends on external view and its frame is not yet ready - results with wrong (or outdated) cell size. Typically happens for the first time view controller laid out all views.You can find similar queries in StackOverflow community :
- Collection view sizeForItemNotWorking
- UICollectionViewCell content wrong size on first load
- How to refresh UICollectionView layout after rotation of the device
- Auto Layout size of CollectionViewCell in relation to CollectionView
- How to set UICollectionViewCell Width and Height programmatically
What is the best solution?
We know `viewWillLayoutSubviews` is responsible for all frame layout calculations in a view controller. At same point, we will have freshly calculated frame ready to be used. Thus, invalidating collection view layout after update will redraw its cell right after external view layout gets updated. Apparently, `invalidateLayout()` will call again flow layout delegate `collectionView: layout sizeForItem:`
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
//... Do some external view layout updates ...//
myCollectionView.collectionViewLayout.invalidateLayout()
}