I am attempting to resize the collectionView
cell inside the masterViewController
of a SplitViewController
but the resizing did not work. I have implemented the necessary viewWillTransition
and invalidateLayout
and it turns out fine if it isn't housed inside a splitViewController
. In my case, I have full screen cell size.
Here's my implementation:
//This CollectionController is housed inside a TabBarController.
//The TabBarController is the masterViewController
class CollectionController: UIViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
lazy var collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
let cv = UICollectionView(frame: CGRect.zero, collectionViewLayout: layout)
cv.translatesAutoresizingMaskIntoConstraints = false
cv.backgroundColor = .gray
cv.dataSource = self
cv.delegate = self
layout.scrollDirection = .horizontal
cv.isPagingEnabled = true
cv.showsHorizontalScrollIndicator = false
cv.showsVerticalScrollIndicator = false
cv.contentInsetAdjustmentBehavior = .always
cv.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cell")
return cv
}()
var spacing: CGFloat = 16
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(collectionView)
collectionView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 3
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
cell.backgroundColor = .blue
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 16
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 16
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let layoutFrame = view.safeAreaLayoutGuide.layoutFrame
let size = CGSize(width: layoutFrame.width, height: layoutFrame.height)
print("SizeForItem", size)
return setUpCellSize(size: size)
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
print("Transit1", size)
layout.itemSize = setUpCellSize(size: size) //With or without this makes no difference
layout.invalidateLayout()
print("Transit2", size)
}
}
func setUpCellSize(size: CGSize) -> CGSize {
return size
}
}
This is the result if implemented purely in the TabBarController
, ie not inside a splitViewController
. Noticed that cells (in blue) are positioned well beneath the status bar. Result is as what is expected and desired.
This is the result if implemented inside a splitViewController
. Noticed that on first rotation to landscape, the cells went above the status bar. And when rotated back to portrait, the cell did not resize back to full screen.
Is there something else that needs to be implemented if the collectionView is placed inside a masterViewController?
EDIT
I add print statements inside sizeForItem
and viewWillTransition
. It turns out that on second rotation, the new size in viewWillTransition
were not passed to the sizeForItem
.
Even explicit calls to setupCellSize
didn't update correctly. It also give the The behavior of the UICollectionViewFlowLayout is not defined
warning. See gif (Gif starts when iPad is in landscape mode).
Also notice that when iPad rotates from landscape -> portrait, blue cell anchors to bottom of statusBar and top of tabBar. This is desired. Then when rotated back from portrait -> landscape, blue cell exceeds statusBar and went underneath tabBar. This is not what I want.