2013-05-16 2 views
32

Ho provato a impostare la durata (con i metodi normali che vorrei provare) per impostare la durata dell'animazione per il metodo selectItemAtIndexPath:animated:scrollPosition: di UICollectionView (o il metodo scrollToItemAtIndexPath:atScrollPosition:animated:). Ho provato [UIView setAnimationDuration] e ho provato a confezionarlo in un CATransaction. Fino a questo punto non sono riuscito a cambiare la durata dell'animazione (anche se ammetto di aver commesso un errore in questa logica).Durata animazione per UICollectionView selectItemAtIndexPath: animato: scrollPosition:

Pensieri?

UPDATE:

ho cercato un buon numero di approcci qui. La soluzione più vicina è fare ciò che faremmo normalmente per l'animazione UIScrollView (impostando l'argomento animato: su NO e avvolgendolo in un blocco di animazione UIView). Questo funziona perfettamente bene per la scrollview. Tuttavia, questo avvita con il processo di creazione UICollectionView per qualche motivo.

Ho incluso un esempio sotto utilizzando due approcci. Ogni approccio presuppone che tu abbia 4 sezioni con 4 elementi in ciascuna sezione. Inoltre, l'animazione presuppone che tu stia passando da 0,0 a 3,3.

Utilizzando animazione di default

Parte del problema qui certamente sembra legato alla UICollectionView. Se si prende il seguente approccio (utilizzando l'opzione di animazione predefinita) - tutto funziona benissimo:

[self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:3 inSection:3] 
           atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally 
             animated:YES]; 

Quando questo viene eseguito, ogni cella si crea in-tra le celle visibili attuali e la cella di destinazione. Ho incluso la registrazione sul metodo collectionView:cellForItemAtIndexPath::

2013-05-18 09:33:24.366 DEF-CV-Testing[75463:c07] Transition 
Cell Created for Index Path: <NSIndexPath 0x8913f40> 2 indexes [0, 1] 
Cell Created for Index Path: <NSIndexPath 0x75112e0> 2 indexes [0, 2] 
Cell Created for Index Path: <NSIndexPath 0xfe1a6c0> 2 indexes [0, 3] 
Cell Created for Index Path: <NSIndexPath 0x89159e0> 2 indexes [1, 0] 
Cell Created for Index Path: <NSIndexPath 0x8a10e70> 2 indexes [1, 1] 
Cell Created for Index Path: <NSIndexPath 0x7510d90> 2 indexes [1, 2] 
Cell Created for Index Path: <NSIndexPath 0x75112a0> 2 indexes [1, 3] 
Cell Created for Index Path: <NSIndexPath 0x8915a00> 2 indexes [2, 0] 
Cell Created for Index Path: <NSIndexPath 0x75111c0> 2 indexes [2, 1] 
Cell Created for Index Path: <NSIndexPath 0xfe17f30> 2 indexes [2, 2] 
Cell Created for Index Path: <NSIndexPath 0xfe190c0> 2 indexes [2, 3] 
Cell Created for Index Path: <NSIndexPath 0xfe16920> 2 indexes [3, 0] 
Cell Created for Index Path: <NSIndexPath 0x75112a0> 2 indexes [3, 1] 
Cell Created for Index Path: <NSIndexPath 0xfe1a4f0> 2 indexes [3, 2] 
Cell Created for Index Path: <NSIndexPath 0x75142d0> 2 indexes [3, 3] 

Utilizzando Animazione personalizzata

Quando avvolgendo il metodo scrollToItemAtIndexPath: in un blocco UIView animazione, gli elementi non vengono create correttamente. Vedere il codice di esempio qui:

[UIView animateWithDuration:5.0 delay:0.0 options:0 animations:^{ 
    [self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:3 inSection:3] 
           atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally 
             animated:NO]; 
} completion:^(BOOL finished) { 
    NSLog(@"Completed"); 
}]; 

Le celle attualmente visibili scompaiono e viene creata solo la destinazione. Ho incluso la stessa registrazione sul metodo collectionView:cellForItemAtIndexPath::

Transition 
Cell Created for Index Path: <NSIndexPath 0x71702f0> 2 indexes [3, 3] 
Completed 
+0

Hai provato a impostare l'animazione su NO e quindi a racchiuderlo in un 'UIView animateWithDuration'? Ecco come lo faccio per una delle mie animazioni scrollview. Faccio '[UIView animtateWithDuration ... [scrollView scrollToRect..' – Kal

+1

Sì. Sfortunatamente questo rovina la creazione della cella. Scorre - ma mostra solo il primo e l'ultimo UICollectionViewsCell nell'animazione. – dtuckernet

+0

Solo per curiosità, hai anche provato a forzare la brutezza dell'animazione all'interno del blocco stesso. '[UIView animateWithDuration: .... animations:^{[self.colectionView scrollToItemAtIndexPath: [0, 1]; self.collectionView.scrollToItemAtIndexpath [0,2]; .... self.collectionView.scrollToItemAtIndexPath [3,3]; ' – Kal

risposta

-1

ho trovato un modo per scorrere manualmente e completamente bypassare la self.collectionView scrollToItemAtIndexPath ..

Ho anche provato ad utilizzare il blocco completamento di un ciclo tra le diverse sezioni , ma questo ha provocato un'esperienza a scatti.

Nota che questo esempio scorre verticalmente: dovresti essere in grado di cambiarlo per scorrere orizzontalmente. Probabilmente dovrai anche regolare gli offset in modo che lo scorrimento si fermi nella posizione desiderata. Ancora una volta, sono sorpreso che l'API non offra un modo per controllare la velocità.

-(void)scrollMethod { 

    // Find the point where scrolling should stop. 
    UICollectionViewLayoutAttributes *attr = [self.collectionView layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:3 inSection:3]]; 

    CGRect cellRect = attr.frame; 

    self.source = self.collectionView.frame.origin; 
    self.destination = cellRect.origin; 
    self.myTimer = [NSTimer scheduledTimerWithTimeInterval:0.001 target:self selector:@selector(scrollOn) userInfo:nil repeats:YES]; 

} 

-(void)scrollOn { 
    self.collectionView.contentOffset = self.source; 
    // If we have crossed where we need to be, quit the timer 
    if (self.source.y > self.destination.y) 
     [self.myTimer invalidate]; 

    self.source = CGPointMake(self.source.x, self.source.y+1); 
} 
+4

@Lifely Potrebbe essere d'aiuto se tu suggerissi effettivamente qualcosa di utile invece di fare downvoting e fare commenti snide. La soluzione sopra ha funzionato e sono ancora vivo :-) – Kal

+0

@Lifely - In realtà un timer può essere una buona pratica per determinati tipi di logica di scorrimento. Vedi il blog di John Resig (creatore di jQuery): http://ejohn.org/blog/learning-from-twitter –

5

ho avuto problemi simili con UITableView che ho risolto dal seguente codice:

[CATransaction begin]; 
[CATransaction setCompletionBlock:onCompletion]; 
[CATransaction setAnimationDuration:duration]; 

[self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:3 inSection:3] 
          atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally 
            animated:YES]; 

[CATransaction commit]; 

Ovviamente, non si può chiamare con animated:NO perché il codice di animazione all'interno del metodo è importante. Utilizzare un CATransaction per avvolgere l'animazione ha funzionato per me.

+8

Purtroppo no, questo non funziona. In questo caso, l'animazione ha luogo - ma alla durata predefinita (non la durata impostata nel metodo 'setAnimationDuration :. – dtuckernet

+0

Grazie mi ha aiutato –

+0

Puoi usare' - [UIView animateWithDuration: animazioni: completamento:] 'per ottenere lo stesso comportamento con meno codice. – orkoden

0

Per me questo funziona. Ovviamente ha bisogno di alcune modifiche (per avere il tempo più accurata e per renderlo lo scorrimento inverso, dal basso verso l'alto Ormai supporta lo scorrimento solo verticale dall'alto verso il basso.)

chiamata qualcosa di simile:

[self scrollToIndexPath:[NSIndexPath indexPathForItem:40 inSection:0] withAnimationDuration:3.0f]; 

e qui è il codice

-(void)scrollToIndexPath:(NSIndexPath *)path withAnimationDuration:(float)duration 
{ 
    NSIndexPath *firstCell = [[self.collectionView indexPathsForVisibleItems] objectAtIndex:0]; 
    UICollectionViewLayoutAttributes *attributesForFirstCell = [self.collectionView layoutAttributesForItemAtIndexPath:firstCell]; 
    CGRect firstCellRect = attributesForFirstCell.frame; 
    CGPoint startPoint = firstCellRect.origin; 

    NSIndexPath *destinationCell = path; 
    UICollectionViewLayoutAttributes *attributesForDestCell = [self.collectionView layoutAttributesForItemAtIndexPath:destinationCell]; 
    CGRect destCellRect = attributesForDestCell.frame; 
    CGPoint destPoint = destCellRect.origin; 

    self.destination = destPoint; 

    float delta = destPoint.y - startPoint.y; 

    float cycle = (delta/(50*duration)); 
    self.pass = (int)cycle + 1; 

    self.myTimer = [NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:@selector(scrollView) userInfo:nil repeats:YES]; 
} 



- (void) scrollView { 

    float w = self.pass; 

    CGPoint scrollPoint = self.collectionView.contentOffset; 
    scrollPoint.y = scrollPoint.y + w; 

    if (scrollPoint.y >= self.destination.y) 
     [self.myTimer invalidate]; 
    [self.collectionView setContentOffset: scrollPoint animated: NO]; 
} 
+0

Raccomanderei di usare un [CADisplayLink] (https://developer.apple.com/library/ios/documentation/QuartzCore/Reference/CADisplayLink_ClassRef/) per questo piuttosto che un NSTimer.VisualisplayLink si attiva automaticamente una volta/frame del sistema. – bcattle

0

Che cosa succede se si mette un po 'di codice nella scrollViewDidScroll:?

Ho un problema simile che ho risolto chiamando selectItemAtIndexPath:animated:scrollPosition e quindi utilizzando scrollViewDidScroll: per eseguire ciò che userei di solito in un blocco di completamento.

Ovviamente probabilmente dovrete tenere traccia di uno BOOL o due per decidere se è necessario eseguire qualcosa in scrollViewDidScroll:.

0

È possibile farlo in modo pulito con la libreria AnimationEngine. Incapsula un CADisplayLink nella sintassi dell'animazione basata su blocchi. Ho inviato una risposta here con un esempio di codice che anima contentOffset. Hai solo bisogno di fare la conversione da indexPath a contentOffset.

-1

La soluzione effettiva è che è necessario eseguire questo scrollToItemAtIndexPath nella coda principale. in modo che solo tu possa ottenere il reale funzionamento di esso.

codice Esempio:

dispatch_async(dispatch_get_main_queue(), ^{ 

    [collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES]; 

});