The issue is the number of columns in the collectionView does NOT stay at 7 (the desired amount) upon rotation. What code change is required to fix this?
It seems the invalidateLayout from the custom UICollectionViewFlowLayout is NOT triggering the sizeForItemAtIndexPath method in the collectionView? Any ideas? I really just want the column resizing to occur via the sizeForItemAtIndexPath upon rotation.
NOTE: I'm not using storyboard here, rather I have a custom view in which I drop in a collectionView and reference my own collectionView classes.
The following code works fine, however upon rotation it does not keep the number of columns to 7 like it should. On running the code initially the console output shows:
GCCalendar - init coder
GCCalendar - commonInit
GCCalendarLayout:invalidateLayout
GCCalendarLayout:invalidateLayout
ViewController:viewWillLayoutSubviews
GCCalendarLayout:invalidateLayout
GCCalendarLayout:prepareLayout
sizeForItemAtIndexPath
.
.
sizeForItemAtIndexPath
minimumInteritemSpacingForSectionAtIndex
minimumLineSpacingForSectionAtIndex
GCCalendarLayout:collectionViewContentSize
GCCalendarLayout:layoutAttributesForElementsInRect
GCCalendarLayout:collectionViewContentSize
ViewController:viewWillLayoutSubviews
GCCalendarCell:drawRect
.
.
GCCalendarCell:drawRect
However then rotating the screen I see the following:
ViewController:viewWillLayoutSubviews
GCCalendarLayout:shouldInvalidateLayoutForBoundsChange
GCCalendarLayout:invalidateLayout
GCCalendarLayout:prepareLayout
GCCalendarLayout:collectionViewContentSize
GCCalendarLayout:layoutAttributesForElementsInRect
GCCalendarLayout:collectionViewContentSize
So the issue is "sizeForItemAtIndexPath" never got called????
Output Code on Rotation
Note: "sizeForItemAtIndexPath" is not triggered even though "invalidateLayout" is
ViewController:viewWillLayoutSubviews GCCalendarLayout:shouldInvalidateLayoutForBoundsChange GCCalendarLayout:invalidateLayout
**My Custom View that houses the collection View **
import UIKit
@IBDesignable class GCCalendarView: UIView {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
// Private
private func commonInit() {
if self.subviews.count == 0 {
let bundle = NSBundle(forClass: self.dynamicType)
let nib = UINib(nibName: "GCCalendarView", bundle: bundle)
let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView
view.frame = bounds
view.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
addSubview(view)
}
}
}
Custom Collection View
import UIKit
class GCCalendar : UICollectionView, UICollectionViewDataSource, UICollectionViewDelegate {
// Init ---------------
func commonInit(coder aDecoder: NSCoder) {
print("GCCalendar - commonInit")
self.registerClass(GCCalendarCell.self, forCellWithReuseIdentifier: "GCCalendarCell")
self.dataSource = self
self.delegate = self
let layout : GCCalendarLayout = GCCalendarLayout(coder: aDecoder)!
self.setCollectionViewLayout(layout, animated: false)
self.backgroundColor = UIColor.whiteColor()
}
required init?(coder aDecoder: NSCoder) {
print("GCCalendar - init coder")
super.init(coder: aDecoder)
commonInit(coder: aDecoder)
}
// UICollectionViewDelegateFlowLayout ------------
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
print("sizeForItemAtIndexPath")
let w : CGFloat = floor(self.frame.size.width/7)
return CGSize(width: w, height: w)
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int) ->
CGFloat {
print("minimumInteritemSpacingForSectionAtIndex")
return 0.0
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
print("minimumLineSpacingForSectionAtIndex")
return 0.0
}
// UICollectionViewDataSource -------------------
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 21
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("GCCalendarCell", forIndexPath: indexPath) as? GCCalendarCell
return cell!
}
}
** Custom CollectionView Cell **
import UIKit
class GCCalendarCell: UICollectionViewCell {
@IBOutlet weak var title : UITextField!
@IBOutlet weak var date: UILabel!
required init?(coder aDecoder: NSCoder) {
print("GCCalendarCell - init:coder")
super.init(coder: aDecoder)
commonInit()
}
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
override func drawRect(rect: CGRect) {
print("GCCalendarCell:drawRect")
self.layer.borderWidth = 1
self.layer.borderColor = UIColor.grayColor().CGColor
}
// Private
private func commonInit() {
let bundle = NSBundle(forClass: self.dynamicType)
let nib = UINib(nibName: "GCCalendarCell", bundle: bundle)
let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView
view.frame = bounds
view.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
addSubview(view)
}
}
Custom Layout
import UIKit
class GCCalendarLayout : UICollectionViewFlowLayout {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool {
print("GCCalendarLayout:shouldInvalidateLayoutForBoundsChange")
return true
}
override func invalidateLayout() {
print("GCCalendarLayout:invalidateLayout")
super.invalidateLayout()
}
override func prepareForCollectionViewUpdates(updateItems: [UICollectionViewUpdateItem]) {
print("GCCalendarLayout:prepareForCollectionViewUpdates")
super.prepareForCollectionViewUpdates(updateItems)
}
override func finalizeCollectionViewUpdates() {
print("GCCalendarLayout:finalizeCollectionViewUpdates")
super.finalizeCollectionViewUpdates()
}
}
EDIT : Try this in your viewController :
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)
{
(self.collectionview.collectionViewLayout).setItemSize(CGSizeMake(floor(size.width / 7), floor(size.width / 7)))
self.collectionview.collectionViewLayout.invalidateLayout()
}
if you are using Storyboard Set the CollectionviewFlowLayout Class In storyboard I attached Bellow
Nothing helped for me from the existing answers (iPhone X Simulator iOS 11.2).
I've found that changing of estimatedSize
helps for me with this problem:
<...>
//***new line
flowLayout.estimatedItemSize = [self getIconSize];//get a new size for items
[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