In my app, I have a full-screen paging collection view and each cell needs to be full-screen as well, so the collection view layout's item size needs to be the same size as the view controller's view's bounds size. To do this, in viewDidLayoutSubviews
I'm simply setting the item size and it is working as intended. When I present this screen, viewDidLayoutSubviews
is called 3 times and each time the view's bounds size is 375.0 x 667.0 for iPhone 7. The cell is sized those same dimensions as expected.
But when using 3D Touch peek and pop to present this screen, the cell is not sized as expected, neither when peeking nor popping. viewDidLayoutSubviews
is called 4 times, with these bounds sizes:
--- peek triggered ---
375.0 x 569.524495677234
375.0 x 569.524495677234
375.0 x 720.821325648415
--- pop triggered ---
375.0 x 667.0
When peeking, the collection view is 'full-screen' as expected with a height of 721, and the cell has the expected width of 375, but the cell height is 569 when it should be 721. Upon popping, the collection view height changes to 667 as expected but the cell height is still 569.
I've tried calling collectionView.layoutIfNeeded()
after setting the itemSize
but the result is the same. Why isn't the collection view updating the cell size here?
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
print("\(view.bounds.width) x \(view.bounds.height)")
let boundsSize = CGSize(width: Int(view.bounds.width), height: Int(view.bounds.height))
let flowLayout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
if flowLayout.itemSize != boundsSize {
flowLayout.itemSize = boundsSize
collectionView.layoutIfNeeded() //this doens't help
}
}
Change the collection view's 'Estimate Size' from the inspector to 'None'! None of the above answers worked for me.
It seems it's a bug of UICollectionViewFlowLayout, I have to call prepare() before invalidateLayout()
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
guard let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout else
{
return
}
layout.itemSize = cellSize
layout.minimumLineSpacing = space
layout.prepare() // <-- call prepare before invalidateLayout
layout.invalidateLayout()
}
Try replacing collectionView.layoutIfNeeded()
by flowLayout.invalidateLayout()
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
print("\(view.bounds.width) x \(view.bounds.height)")
let boundsSize = CGSize(width: Int(view.bounds.width), height: Int(view.bounds.height))
let flowLayout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
if flowLayout.itemSize != boundsSize {
flowLayout.itemSize = boundsSize
debugPrint("Called")
flowLayout.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