2015-10-14 20 views
8

Il problema è il numero di colonne nella collectionView non rimane a 7 (la quantità desiderata) a rotazione. Quale modifica del codice è necessaria per risolvere questo problema?perché invalidateLayout non sta attivando sizeForItemAtIndexPath in UICollectionView? (codice allegato)

Sembra che invalidateLayout dall'usuale UICollectionViewFlowLayout NON stia attivando il metodo sizeForItemAtIndexPath in collectionView? Qualche idea? Voglio solo che il ridimensionamento della colonna avvenga tramite la dimensioneForItemAtIndexPath a rotazione.

NOTA: non sto usando lo storyboard qui, ma ho una vista personalizzata in cui faccio cadere una collezioneView e faccio riferimento alle mie classi collectionView.

Il seguente codice funziona correttamente, tuttavia a rotazione non mantiene il numero di colonne su 7 come dovrebbe. Sulla esecuzione del codice inizialmente gli spettacoli di uscita della console:

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 

Comunque poi ruotando lo schermo compaiono i seguenti:

ViewController:viewWillLayoutSubviews 
GCCalendarLayout:shouldInvalidateLayoutForBoundsChange 
GCCalendarLayout:invalidateLayout 
GCCalendarLayout:prepareLayout 
GCCalendarLayout:collectionViewContentSize 
GCCalendarLayout:layoutAttributesForElementsInRect 
GCCalendarLayout:collectionViewContentSize 

Quindi il problema è "sizeForItemAtIndexPath" non ha mai avuto chiamato ????

codice uscita a rotazione

Nota: "sizeForItemAtIndexPath" non viene attivato anche se "invalidateLayout" è

ViewController: viewWillLayoutSubviews GCCalendarLayout: shouldInvalidateLayoutForBoundsChange GCCalendarLayout: invalidateLayout

** My Custom Guarda che ospita la collezione vista **

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) 
     } 
    } 

} 

personalizzato collezione guarda

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! 
    } 
} 

** personalizzato CollectionView cellulare **

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) 
    } 

} 

layout personalizzato

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() 
    } 


} 
+0

stai usando storyboard –

+0

no. non usare lo storyboard – Greg

+0

Potrei aiutarti ma non lo so. Puoi leggere obj-c? – Kujey

risposta

8

EDIT: Prova questo nella vostra 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() 
} 
+0

devo avere questo diritto in quanto impostato correttamente le dimensioni durante l'esecuzione, è proprio alla rotazione cambia le questioni si pone – Greg

+0

Probabilmente sì. Ma ancora, potresti aggiungere un log alla funzione itemSize del tuo flowlayout personalizzato, solo per vedere se è chiamato su rotazione. – Kujey

+0

sizeForItemAtIndexPath (se è questo che vuoi dire) non viene chiamato a rotazione ... che è il problema – Greg

1

se si utilizza Storyboard Impostare la classe CollectionviewFlowLayout In storyboard ho attaccato Bellow

this is FlowLayout

Classname Set here

+0

no. Non utilizzare storyboard – Greg

0

@ soluzione Kujey può essere applicato a UIView senza accedere UIViewController:

func traitCollectionDidChange(previousTraitCollection : UITraitCollection) { 
    super.traitCollectionDidChange(previousTraitCollection) 
    self.collectionView.collectionViewLayout.invalidateLayout() 
} 
+0

@EricAya Credo che il linguaggio di programmazione non è veramente importante per questa domanda. – k06a

0

Nulla mi ha aiutato dalle risposte esistenti (iPhone X Simulator iOS 11.2).
Ho scoperto che la modifica di estimatedSize aiuta per me con questo problema:

<...> 
//***new line 
flowLayout.estimatedItemSize = [self getIconSize];//get a new size for items 

[flowLayout invalidateLayout]; 
<...>