8

Проблема заключается в том, что количество столбцов в коллекцииView не остается на 7 (желаемая сумма) при вращении. Какое изменение кода требуется для исправления этого?Почему invalidateLayout не запускает sizeForItemAtIndexPath в UICollectionView? (код прилагается)

Кажется, invalidateLayout из пользовательского UICollectionViewFlowLayout НЕ запускает метод sizeForItemAtIndexPath в коллекцииView? Есть идеи? Я просто хочу, чтобы изменение размера столбца происходило через sizeForItemAtIndexPath при вращении.

ПРИМЕЧАНИЕ: Я не использую раскадровку здесь, скорее у меня есть пользовательский вид, в котором я бросаю в collectionView и ссылаюсь на свои собственные классы collectionView.

Следующий код работает нормально, однако при вращении он не сохраняет количество столбцов до 7, как должно. На выполнение кода изначально выходных шоу консоли:

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 

Однако затем поворачивать экран я вижу следующее:

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

Так что вопрос «sizeForItemAtIndexPath» никогда не был призван ????

код выхода на Rotation

Примечание: "sizeForItemAtIndexPath" не срабатывает, даже если "invalidateLayout" является

ViewController: viewWillLayoutSubviews GCCalendarLayout: shouldInvalidateLayoutForBoundsChange GCCalendarLayout: invalidateLayout

** My Custom Посмотреть, где находится коллекция 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) 
     } 
    } 

} 

Пользовательские коллекции Просмотр

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

** Пользовательские 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) 
    } 

} 

пользовательского макета

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

вы используете раскадровку –

+0

нет. не используя раскадровку – Greg

+0

Я мог бы вам помочь, но я не знаю быстро. Можете ли вы прочитать obj-c? – Kujey

ответ

8

EDIT: Попробуйте это в 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

Я должен иметь это право, поскольку он правильно устанавливает размеры при запуске, он просто при повороте меняет проблемы – Greg

+0

Возможно, да. Но все же, вы могли бы добавить журнал к функции itemSize своего пользовательского flowlayout, просто чтобы увидеть, вызвано ли оно вращением. – Kujey

+0

sizeForItemAtIndexPath (если это то, что вы имеете в виду) не вызывается при вращении ... вот в чем проблема – Greg

1

если вы используете раскадровки Установите CollectionviewFlowLayout класса В раскадровке я прикрепил пыльник

this is FlowLayout

Classname Set here

+0

нет. не используя раскадровку – Greg

0

@ решение Kujey в может применяться к UIView без доступа к UIViewController:

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

@EricAya Я думаю, что язык программирования не очень важен для этого вопроса. – k06a

0

Ничего не помогло мне в существующих ответах (iPhone X Simulator iOS 11.2).
Я обнаружил, что изменение estimatedSize помогает мне с этой проблемой:

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

[flowLayout invalidateLayout]; 
<...> 
Смежные вопросы