2015-12-02 16 views
5

Ho un progetto semplice con uno storyboard che contiene solo un singolo un UICollectionViewController, costruito con Xcode 7.1.1 per iOS 9,1cellule UICollectionView ridimensionamento quando l'eliminazione di elementi con 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 
     } 
    } 
} 

Quando si eliminano le cellule dalla vista collezione , tutte le celle rimanenti si animano sul loro estimatedItemSize e quindi tornano alla dimensione corretta.

enter image description here

È interessante notare che questo produce Layout automatico avvertenze vincolo per ogni cella quando si verifica l'animazione:

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> 

Il mio primo pensiero è stato che rompere questi vincoli era quello che stava causando il problema di ridimensionamento.

Aggiornamento awakeFromNib metodo della cellula:

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

correzioni gli avvertimenti, ma il problema si verifica ancora.

ho cercato ri-aggiungendo i miei vincoli tra la cellula e il suo contentView, ma questo non ha risolto il problema:

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

Pensieri?

+0

Due anni dopo, e sto affrontando lo stesso problema, ancora. Ci sono un paio di radar per questo http://www.openradar.me/23728611; Supponiamo che uno sia tuo, però? :) – Roland

+0

Aggiunto un duplicato: rdar: // 35717256 – Roland

risposta

0

layout di flusso calcola le dimensioni effettive delle celle dopo aver eseguito il layout in base alle dimensioni stimate per definire quali sono visibili. Dopodiché regola il layout in base alle dimensioni reali.

Tuttavia, quando si anima, quando calcola la posizione iniziale per l'animazione, non raggiunge lo stadio di dequeue delle celle e esegue il layout automatico lì, quindi utilizza solo le dimensioni stimate.

Il modo più semplice è provare a fornire le dimensioni stimate più vicine o se è possibile fornire la dimensione nel delegato nella chiamata sizeForItemAt.

Nel mio caso, stavo cercando di animare layoutAttributes senza inserire o l'eliminazione di cellule e per questo caso specifico mi sottoclasse UICollectionViewFlowLayout e poi override questo metodo:

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

questo modo si evita il ricalcolo attributi layout con dimensioni stimate in cui nulla è stato cambiato.

Problemi correlati