2015-10-14 13 views
8

Vấn đề là số lượng cột trong collectionView KHÔNG ở mức 7 (số tiền mong muốn) khi xoay vòng. Cần thay đổi mã nào để sửa lỗi này?tại sao invalidateLayout không kích hoạt sizeForItemAtIndexPath trong UICollectionView? (mã đính kèm)

Dường như invalidateLayout từ UICollectionViewFlowLayout tùy chỉnh KHÔNG kích hoạt phương thức sizeForItemAtIndexPath trong collectionView? Ý tưởng nào? Tôi thực sự chỉ muốn thay đổi kích thước cột để xảy ra thông qua các sizeForItemAtIndexPath khi xoay.

LƯU Ý: Tôi không sử dụng bảng phân cảnh ở đây, thay vào đó tôi có chế độ xem tùy chỉnh trong đó tôi thả vào collectionView và tham chiếu các lớp collectionView của riêng tôi.

Mã sau hoạt động tốt, tuy nhiên khi xoay vòng, nó không giữ số cột là 7. Khi chạy phần mã ban đầu giao diện điều khiển chương trình đầu ra:

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 

Tuy nhiên sau đó xoay màn hình tôi thấy như sau:

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

Vì vậy, vấn đề là "sizeForItemAtIndexPath" không bao giờ bị gọi là ????

Output Mã trên Rotation

Lưu ý: "sizeForItemAtIndexPath" không được kích hoạt mặc dù "invalidateLayout" là

ViewController: viewWillLayoutSubviews GCCalendarLayout: shouldInvalidateLayoutForBoundsChange GCCalendarLayout: invalidateLayout

** Tùy chỉnh của tôi Xem mà nhà sưu tập Xem **

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

} 

Tuỳ chỉnh Collection Xem

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

** Tuỳ chỉnh CollectionView di động **

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

} 

Tuỳ chỉnh 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() 
    } 


} 
+0

bạn đang sử dụng Storyboard –

+0

không. không sử dụng bảng phân cảnh – Greg

+0

Tôi có thể giúp bạn nhưng tôi không biết nhanh. Bạn có thể đọc obj-c không? – Kujey

Trả lời

8

EDIT: Hãy thử điều này trong viewController của bạn:

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

Tôi phải có quyền này vì nó đặt kích thước chính xác khi chạy, nó chỉ xoay vòng các vấn đề phát sinh – Greg

+0

Có thể là có. Tuy nhiên, bạn có thể thêm nhật ký vào chức năng itemSize của flowlayout tùy chỉnh của bạn, chỉ để xem nó có được gọi là xoay vòng hay không. – Kujey

+0

sizeForItemAtIndexPath (nếu đó là ý của bạn) không được gọi là xoay vòng ... đó là vấn đề – Greg

1

nếu bạn đang sử dụng Storyboard Set Class CollectionviewFlowLayout Trong kịch bản I kèm Bellow

this is FlowLayout

Classname Set here

+0

không. không sử dụng bảng phân cảnh – Greg

0

@ giải pháp Kujey của có thể được áp dụng cho UIView mà không cần truy cập UIViewController:

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

@EricAya Tôi nghĩ ngôn ngữ lập trình không thực sự quan trọng đối với câu hỏi này. – k06a

0

Không có gì giúp tôi từ các câu trả lời hiện có (iPhone X Simulator iOS 11.2).
tôi đã tìm thấy rằng việc thay đổi của estimatedSize giúp cho tôi với vấn đề này:

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

[flowLayout invalidateLayout]; 
<...> 
Các vấn đề liên quan