2013-06-04 9 views
42

Ho un UICollectionViewController che utilizza uno standard UICollectionViewFlowLayout per visualizzare una singola colonna verticale di celle. Sto tentando di creare un'animazione di espansione/compressione su una cella quando viene toccata una cella. Io uso il seguente codice per ottenere questo risultato:UICollectionView l'animazione della modifica della dimensione della cella causa un comportamento indesiderato

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath (NSIndexPath *)indexPath 
{ 
    [self.feedManager setCurrentlySelectedCellIndex:indexPath.item]; 
    [self.collectionView performBatchUpdates:nil completion:nil]; 
} 

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath 
{ 
    //Return the size of each cell to draw 
    CGSize cellSize = (CGSize) { .width = 320, .height = [self.feedManager heightForCellAtIndexPath:indexPath] }; 
    return cellSize; 
} 

La proprietà 'selectedCellIndex' sul mio oggetto la gestione dice al modello di dati per restituire un formato espanso o collassato all'interno del heightForCellAtIndexpath:

[self.collectionView performBatchUpdates:nil completion:nil]; 

Poi il performBatchUpdates:completiong: il metodo anima bene questo cambiamento di dimensione. Però! Quando si verifica l'animazione, la cella espandibile potrebbe causare una cella parzialmente visibile nella parte inferiore dello schermo per uscire dallo schermo.

Se questo è il caso e successivamente collasso questa cella, la cella ora disattivata scatterà alla sua posizione precedente senza animazione, mentre tutte le altre celle visibili si animeranno come desiderato. La mia intuizione dice che questo è il comportamento corretto poiché la cella è fuori dallo schermo quando viene eseguita l'animazione di compressione e non viene inclusa nel processo di rendering dell'animazione. La mia domanda diventa, come posso evitare che ciò accada?

Preferirei che tutte le celle si animino insieme, indipendentemente dal fatto che siano sullo schermo o meno. qualche idea?

+0

Ho trovato un problema molto simile quando spuntavo su http://stackoverflow.com/questions/13698275/uicollectionview-moveitematindexpathtoindexpath-issues-moving-items-not-on-scr –

+0

Sembra che le celle riutilizzabili si stiano intromettendo dell'animazione poiché la cella fuori schermo viene contrassegnata come pronta per il riutilizzo. Qualche idea su come impedire che una cella venga contrassegnata per il riutilizzo? –

+0

Ho esattamente lo stesso problema e mi piacerebbe davvero una soluzione, anche se quella soluzione è un numero radar! – jrturton

risposta

27

Questo è un bug UICollectionViewFlowLayout, ma c'è una soluzione alternativa. Il problema è che gli attributi restituiti da initialLayoutAttributesForAppearingItemAtIndexPath: hanno i frame sbagliati. Nello specifico, hanno i frame della posizione finale, sullo schermo piuttosto che la posizione iniziale, fuori dallo schermo. Hai solo bisogno di sovrascrivere questo metodo e restituire i frame corretti. La struttura di base della sostituzione sarebbe simile a questa:

- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath 
{ 
    UICollectionViewLayoutAttributes *pose = [super initialLayoutAttributesForAppearingItemAtIndexPath:itemIndexPath]; 
    if (<test for incorrect frame>) { 
     CGRect frame = pose.frame; 
     frame.origin.y = <calculate correct frame>; 
     pose.frame = frame; 
    } 
    return pose; 
} 

sarà responsabile per l'identificazione di scenari in cui hanno bisogno di essere regolato le cornici, che possono comportare mantenere il proprio stato interno. Non ho elaborato questa logica, ma ho fatto un test approssimativo e sono riuscito a ottenere un'animazione fluida.

Generalizzando un po ', è la mia esperienza che lì UICollectionViewFlowLayout è così buggato e ci sono così tanti casi d'angolo con cui fare i conti se hai elementi in movimento avanti e indietro combinati con inserti, cancellazioni o mosse, che Ho trovato più facile stampare i miei semplici layout. Se non hai intenzione di fare inserimenti, eliminazioni o spostamenti, la sostituzione di UICollectionViewFlowLayout potrebbe essere la soluzione migliore.

Fammi sapere se hai bisogno di ulteriore aiuto.

EDIT

Se siete interessati a guardare un layout partito 3-rd, ho open source il mio layout griglia personalizzata VCollectionViewGridLayout e ha aggiunto un progetto di esempio che dimostra liscia altezza della cella in espansione. Prova a eseguire il Expand project. C'è anche un Sort & Filter project con ordinamento e filtro animati. Entrambi i progetti ti consentono di alternare il layout del flusso e il layout della griglia in modo da poter vedere il miglioramento.

+0

Il tuo suggerimento sul frame sbagliato in 'initialLayout ...' era azzeccato. Sto memorizzando gli attributi per le celle più tardi della mia cella selezionata e confrontandoli con i frame restituiti con quel metodo, sostituendoli dove necessario. La mia sottoclasse di layout esistente fa già un sacco di lavoro ma darò un'occhiata al tuo. – jrturton

+1

Oh sì, e ho 200 punti! – jrturton

+0

@TimothyMoose come dovrei includere VCollectionViewLayout e TLIndexPathTools all'interno del mio progetto xcode? Ho appena aggiunto VCollectionViewLayout.h, i file VCollectionViewLayout.m e ho trascinato/rilasciato il file di progetto TLIndexPathTools all'interno del gruppo Frameworks del mio progetto e aggiunto come Dependency e Linked Framework in Fasi di creazione, ma ottengo il seguente errore: Simboli indefiniti per architettura i386: " _OBJC_CLASS _ $ _ NSManagedObject ", referenziato da: objc-class-ref in libTLIndexPathTools.a (TLIndexPathDataModel.o) – ftartaggia

Problemi correlati