2012-11-21 14 views
15

Qualcuno ha visto una risposta decente a questo problema?initialLayoutAttributesForAppearingItemAtIndexPath attivato per tutte le celle visibili, non solo per le celle inserite

initialLayoutAttributesForAppearingItemAtIndexPath sembra essere chiamato per tutte le celle visibili, non solo per la cella inserita. Secondo Apple's own docs:

Per gli articoli spostati, la vista raccolta utilizza i metodi standard per recuperare gli attributi di layout aggiornati dell'articolo. Per gli oggetti di essere inseriti o cancellati, la vista collezione chiama alcuni metodi diversi, che si dovrebbe ignorare per fornire le informazioni di layout appropriata

Il che non suona come quello che sta succedendo ... le altre celle non vengono sono stati spostati, ma sta chiamando initialLayoutAttributesForAppearingItemAtIndexPath per quelli anche spostati.

Ho visto il lavoro in giro usando prepareForCollectionViewUpdates: per tracciare quali indexPath vengono aggiornati e solo cambiandoli, ma questo sembra un po 'strano che stia andando di nuovo i propri documenti. Qualcun altro ha trovato un modo migliore per aggirare questo?

+0

Sto avendo difficoltà a capire anche questo. Tutte le celle visibili vengono ricaricate ogni volta che apporto una modifica alla vista raccolta e non è chiaro come evitarlo. Quando l'utente tocca una cella in una sezione, ricarico l'altra sezione durante l'animazione di una modifica nella cella TAPpata. Il ricarico interrompe le mie animazioni e non riesco a trovare un modo per aggirarlo. – CharlieMezak

risposta

9

Non sei solo. I commenti del file di intestazione UICollectionViewLayout rendono le cose un po 'più chiare.

Per ogni elemento sullo schermo davanti alla invalidazione, finalLayoutAttributesForDisappearingXXX sarà chiamato e un'impostazione animazione dal presente sullo schermo di tali attributi finali.

Per ogni elemento sullo schermo dopo l'invalidazione, initialLayoutAttributesForAppearingXXX sarà chiamata un'animazione configurazione da tali attributi iniziali di quanto finisce sullo schermo.

Fondamentalmente finalLayoutAttributesForDisappearingItemAtIndexPath viene chiamata per ogni elemento sullo schermo prima dell'inizio del blocco animazione, e initialLayoutAttributesForAppearingItemAtIndexPath viene chiamata per ogni articolo dopo le estremità del blocco di animazione. Sta a te mettere in cache la matrice di oggetti UICollectionViewUpdateItem inviati in prepareForCollectionViewUpdates in modo da sapere come impostare gli attributi iniziale e finale. Nel mio caso ho memorizzato nella cache i rettangoli di layout precedenti in prepareLayout, quindi ho conosciuto le posizioni iniziali corrette da utilizzare.

Una cosa che mi ha bloccato per un po 'è che dovresti usare l'implementazione di super initialLayoutAttributesForAppearingItemAtIndexPath e modificare gli attributi che restituisce. Stavo solo chiamando layoutAttributesForItemAtIndexPath nella mia implementazione e le animazioni non funzionavano perché le posizioni del layout erano diverse.

18

Ho trovato this blog post by Mark Pospesel essere utile.
L'autore ha anche corretto il campione WWDC CircleLayout e posted it on Github.

Metodi di interesse:

- (void)prepareForCollectionViewUpdates:(NSArray *)updateItems 
{ 
    // Keep track of insert and delete index paths 
    [super prepareForCollectionViewUpdates:updateItems]; 

    self.deleteIndexPaths = [NSMutableArray array]; 
    self.insertIndexPaths = [NSMutableArray array]; 

    for (UICollectionViewUpdateItem *update in updateItems) 
    { 
     if (update.updateAction == UICollectionUpdateActionDelete) 
     { 
      [self.deleteIndexPaths addObject:update.indexPathBeforeUpdate]; 
     } 
     else if (update.updateAction == UICollectionUpdateActionInsert) 
     { 
      [self.insertIndexPaths addObject:update.indexPathAfterUpdate]; 
     } 
    } 
} 

- (void)finalizeCollectionViewUpdates 
{ 
    [super finalizeCollectionViewUpdates]; 
    // release the insert and delete index paths 
    self.deleteIndexPaths = nil; 
    self.insertIndexPaths = nil; 
} 

// Note: name of method changed 
// Also this gets called for all visible cells (not just the inserted ones) and 
// even gets called when deleting cells! 
- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath 
{ 
    // Must call super 
    UICollectionViewLayoutAttributes *attributes = [super initialLayoutAttributesForAppearingItemAtIndexPath:itemIndexPath]; 

    if ([self.insertIndexPaths containsObject:itemIndexPath]) 
    { 
     // only change attributes on inserted cells 
     if (!attributes) 
      attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath]; 

     // Configure attributes ... 
     attributes.alpha = 0.0; 
     attributes.center = CGPointMake(_center.x, _center.y); 
    } 

    return attributes; 
} 

// Note: name of method changed 
// Also this gets called for all visible cells (not just the deleted ones) and 
// even gets called when inserting cells! 
- (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingItemAtIndexPath:(NSIndexPath *)itemIndexPath 
{ 
    // So far, calling super hasn't been strictly necessary here, but leaving it in 
    // for good measure 
    UICollectionViewLayoutAttributes *attributes = [super finalLayoutAttributesForDisappearingItemAtIndexPath:itemIndexPath]; 

    if ([self.deleteIndexPaths containsObject:itemIndexPath]) 
    { 
     // only change attributes on deleted cells 
     if (!attributes) 
      attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath]; 

     // Configure attributes ... 
     attributes.alpha = 0.0; 
     attributes.center = CGPointMake(_center.x, _center.y); 
     attributes.transform3D = CATransform3DMakeScale(0.1, 0.1, 1.0); 
    } 

    return attributes; 
} 
0

Se hai una sottoclasse UICollectionViewFlowLayout, è possibile chiamare l'implementazione super. Una volta ottenuto il layout iniziale predefinito, è possibile verificare la presenza di un .alpha di 0. Se alpha è diverso da 0, la cella viene spostata, se è 0 viene inserita.

Un po 'di trucco, lo so, ma funziona.

Swift 2.0 attuazione segue:

override func initialLayoutAttributesForAppearingItemAtIndexPath(itemIndexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? { 


    guard let attributes = super.initialLayoutAttributesForAppearingItemAtIndexPath(itemIndexPath) where attributes.alpha == 0 else { 
     return nil 
    } 

    // modify attributes for insertion here 

    return attributes 

} 
0

Assicurarsi che si sta utilizzando una nuova firma di metodo a Swift 3. correzione automatica non funziona per questo metodo:

func initialLayoutAttributesForAppearingItem(at itemIndexPath: IndexPath) -> UICollectionViewLayoutAttributes? 
Problemi correlati