2015-12-02 127 views
5

刪除項目時調整我有隻包含單一一個UICollectionViewController,在Xcode 7.1.1內置於iOS 9.1 Storyboard的簡單項目UICollectionView細胞estimatedItemSize

class ViewController: UICollectionViewController { 

    var values = ["tortile", "jetty", "tisane", "glaucia", "formic", "agile", "eider", "rooter", "nowhence", "hydrus", "outdo", "godsend", "tinkler", "lipscomb", "hamlet", "unbreeched", "fischer", "beastings", "bravely", "bosky", "ridgefield", "sunfast", "karol", "loudmouth", "liam", "zunyite", "kneepad", "ashburn", "lowness", "wencher", "bedwards", "guaira", "afeared", "hermon", "dormered", "uhde", "rusher", "allyou", "potluck", "campshed", "reeda", "bayonne", "preclose", "luncheon", "untombed", "northern", "gjukung", "bratticed", "zeugma", "raker"] 

    @IBOutlet weak var flowLayout: UICollectionViewFlowLayout! 
    override func viewDidLoad() { 
     super.viewDidLoad()   
     flowLayout.estimatedItemSize = CGSize(width: 10, height: 10) 
    } 

    override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 
     return values.count 
    } 

    override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { 
     let cell = collectionView.dequeueReusableCellWithReuseIdentifier("MyCell", forIndexPath: indexPath) as! MyCell 
     cell.name = values[indexPath.row] 
     return cell 
    } 

    override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) { 
     values.removeAtIndex(indexPath.row) 
     collectionView.deleteItemsAtIndexPaths([indexPath]) 
    } 
} 

class MyCell: UICollectionViewCell { 

    @IBOutlet weak var label: UILabel! 

    var name: String? { 
     didSet { 
      label.text = name 
     } 
    } 
} 

當刪除從集合視圖的細胞,所有剩餘的單元格會以其estimatedItemSize生成動畫,然後交換回正確的大小。

enter image description here

有趣的是,當動畫出現此會爲每一個細胞自動佈局約束警告:

2015-12-02 14:30:45.236 CollectionTest[1631:427853] Unable to simultaneously satisfy constraints. 
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
     (1) look at each constraint and try to figure out which you don't expect; 
     (2) find the code that added the unwanted constraint or constraints and fix it. 
    (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSAutoresizingMaskLayoutConstraint:0x14556f780 h=--& v=--& H:[UIView:0x1456ac6c0(10)]>", 
    "<NSLayoutConstraint:0x1456acfd0 UIView:0x1456ac6c0.trailingMargin == UILabel:0x1456ac830'raker'.trailing>", 
    "<NSLayoutConstraint:0x1456ad020 UILabel:0x1456ac830'raker'.leading == UIView:0x1456ac6c0.leadingMargin>" 
) 

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x1456acfd0 UIView:0x1456ac6c0.trailingMargin == UILabel:0x1456ac830'raker'.trailing> 

我最初的想法是打破這些制約因素是什麼導致調整大小的問題。

更新小區的awakeFromNib方法:

override func awakeFromNib() { 
    super.awakeFromNib() 
    contentView.translatesAutoresizingMaskIntoConstraints = false 
} 

修復的警告,但問題仍然存在。

我試圖重新添加細胞及其contentView之間我自己的約束,但這並沒有解決問題:

override func awakeFromNib() { 
    super.awakeFromNib() 
    contentView.translatesAutoresizingMaskIntoConstraints = false 

    for constraint in [ 
     contentView.leadingAnchor.constraintEqualToAnchor(leadingAnchor), 
     contentView.trailingAnchor.constraintEqualToAnchor(trailingAnchor), 
     contentView.topAnchor.constraintEqualToAnchor(topAnchor), 
     contentView.bottomAnchor.constraintEqualToAnchor(bottomAnchor)] 
    { 
     constraint.priority = 999 
     constraint.active = true 
    } 
} 

的思考?

+0

兩年後,我仍面臨同樣的問題。有幾個雷達用於它http://www.openradar.me/23728611;但是,假設你是你的? :) – Roland

+0

添加了一個dupe:rdar:// 35717256 – Roland

回答

0

流程佈局根據估計尺寸計算佈局後,計算單元的實際尺寸,以確定哪些尺寸可見。之後,它會根據實際尺寸調整佈局。

但是,當它動畫時,當它計算動畫的初始位置時,它不會達到出列單元格並在那裏運行自動佈局的階段,因此它只使用估計大小。

最簡單的方法是嘗試給出最接近的估計尺寸,或者您可以在sizeForItemAt調用中的代表中提供尺寸。

以我爲例,我是想不插入或刪除單元格動畫layoutAttributes和特定情況下,我的子類UICollectionViewFlowLayout然後重寫了這個方法:

override func invalidateLayout(with context: UICollectionViewLayoutInvalidationContext) { 
    if !context.invalidateEverything && context.invalidatedItemIndexPaths == nil && context.contentOffsetAdjustment == .zero && context.contentSizeAdjustment == .zero { 
     return 
    } 
    super.invalidateLayout(with: context) 
} 

這可以防止重新計算使用估計的尺寸沒事的時候佈局屬性已經變了。