Crear un desplazamiento lento a indexPath en UICollectionView

Estoy trabajando en un proyecto en el que estoy usando un UICollectionView para crear un 'ticker de image' donde estoy publicitando una serie de logotypes. La colecciónView es un artículo alto y doce artículos de largo, y muestra dos o tres artículos a la vez (dependiendo del tamaño de los logotypes visibles).

Me gustaría hacer una lenta animation de desplazamiento automático desde el primer elemento hasta el último y luego repetir.

¿Alguien ha podido hacer que esto funcione? Puedo hacer que el desplazamiento funcione usando

[myCollection scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:(myImages.count -1) inSection:0] atScrollPosition:UICollectionViewScrollPositionRight animated:YES]; 

¡Pero esto es demasiado rápido!

 [UIView animateWithDuration:10 delay:2 options:(UIViewAnimationOptionAutoreverse + UIViewAnimationOptionRepeat) animations:^{ [myCollection scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:(myImages.count -1) inSection:0] atScrollPosition:UICollectionViewScrollPositionRight animated:NO]; } completion:nil]; 

Esto produce la velocidad de desplazamiento deseada, pero solo las últimas celdas son visibles en la serie. Sospecho que ellos (e incluso las celdas visibles iniciales) están siendo eliminados de inmediato.

¿Alguna idea?

Puedes probar este enfoque:

 @property (nonatomic, assign) CGPoint scrollingPoint, endPoint; @property (nonatomic, strong) NSTimer *scrollingTimer; @synthesize scrollingPoint, endPoint; @synthesize scrollingTimer; - (void)scrollSlowly { // Set the point where the scrolling stops. self.endPoint = CGPointMake(0, 300); // Assuming that you are starting at {0, 0} and scrolling along the x-axis. self.scrollingPoint = CGPointMake(0, 0); // Change the timer interval for speed regulation. self.scrollingTimer = [NSTimer scheduledTimerWithTimeInterval:0.015 target:self selector:@selector(scrollSlowlyToPoint) userInfo:nil repeats:YES]; } - (void)scrollSlowlyToPoint { self.collectionView.contentOffset = self.scrollingPoint; // Here you have to respond to user interactions or else the scrolling will not stop until it reaches the endPoint. if (CGPointEqualToPoint(self.scrollingPoint, self.endPoint)) { [self.scrollingTimer invalidate]; } // Going one pixel to the right. self.scrollingPoint = CGPointMake(self.scrollingPoint.x, self.scrollingPoint.y+1); } 

Utilizo un truco de "1 pixel offset" . Cuando se desplaza mediante progtwigción, simplemente configure el final contentOffset.x a 1 píxel más / less de lo que debería. Esto debería ser imperceptible. Y en el bloque de finalización, establézcalo en valor real. De esa forma, puede evitar el problema de eliminación de células prematuras y get una animation de desplazamiento suave;)

Aquí hay un ejemplo de desplazamiento a la página derecha (por ejemplo, de la página 1 a 2). Tenga en count que en las animations: bloque, en realidad, se desplaza un píxel less ( pageWidth * nextPage - 1 ). Luego restaura el valor correcto en la completion: bloquear.

 CGFloat pageWidth = self.collectionView.frame.size.width; int currentPage = self.collectionView.contentOffset.x / pageWidth; int nextPage = currentPage + 1; [UIView animateWithDuration:1 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ [self.collectionView setContentOffset:CGPointMake(pageWidth * nextPage - 1, 0)]; } completion:^(BOOL finished) { [self.collectionView setContentOffset:CGPointMake(pageWidth * nextPage, 0)]; }]; 

También podría tener un desplazamiento "lento" hasta el final de UICollectionView sin tener que "saltar" de la ruta de índice a la ruta de índice. TVOS esto rápidamente para una vista de colección en una aplicación TVOS :

 func autoScroll () { let co = collectionView.contentOffset.x let no = co + 1 UIView.animateWithDuration(0.001, delay: 0, options: .CurveEaseInOut, animations: { [weak self]() -> Void in self?.collectionView.contentOffset = CGPoint(x: no, y: 0) }) { [weak self](finished) -> Void in self?.autoScroll() } } 

Acabo de llamar a autoScroll() en viewDidLoad() y el rest se encarga de eso mismo. La velocidad del desplazamiento se decide por el time de animation de UIView . Podrías (no lo he intentado) agregar un NSTimer con 0 segundos en su lugar, por lo que puedes invalidarlo en userscroll.

Para cualquier otra persona que encuentre esto, he actualizado la sugerencia de Masa para trabajar en Swift y he introducido un poco de relajación hacia el final, por lo que actúa más como la llamada animada original scrollItemsToIndexPath. Tengo cientos de artículos en mi opinión por lo que un ritmo constante no fue una opción para mí.

 var scrollPoint: CGPoint? var endPoint: CGPoint? var scrollTimer: NSTimer? var scrollingUp = false func scrollToIndexPath(path: NSIndexPath) { let atts = self.collectionView!.layoutAttributesForItemAtIndexPath(path) self.endPoint = CGPointMake(0, atts!.frame.origin.y - self.collectionView!.contentInset.top) self.scrollPoint = self.collectionView!.contentOffset self.scrollingUp = self.collectionView!.contentOffset.y > self.endPoint!.y self.scrollTimer?.invalidate() self.scrollTimer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: "scrollTimerTriggenetworking:", userInfo: nil, repeats: true) } func scrollTimerTriggenetworking(timer: NSTimer) { let dif = fabs(self.scrollPoint!.y - self.endPoint!.y) / 1000.0 let modifier: CGFloat = self.scrollingUp ? -30 : 30 self.scrollPoint = CGPointMake(self.scrollPoint!.x, self.scrollPoint!.y + (modifier * dif)) self.collectionView?.contentOffset = self.scrollPoint! if self.scrollingUp && self.collectionView!.contentOffset.y <= self.endPoint!.y { self.collectionView!.contentOffset = self.endPoint! timer.invalidate() } else if !self.scrollingUp && self.collectionView!.contentOffset.y >= self.endPoint!.y { self.collectionView!.contentOffset = self.endPoint! timer.invalidate() } } 

Ajustar los valores de dif y modificador ajusta la duración / nivel de facilidad para la mayoría de las situaciones.

En el file .h, declare este timer,

 NSTimer *Timer; 

Coloque este código del timer,

  [CollectionView reloadData]; Timer = [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(AutoScroll) userInfo:nil repeats:YES]; 

entonces,

 #pragma mark- Auto scroll image collectionview -(void)AutoScroll { if (i<[Array count]) { NSIndexPath *IndexPath = [NSIndexPath indexPathForRow:i inSection:0]; [self.ImageCollectionView scrollToItemAtIndexPath:IndexPath atScrollPosition:UICollectionViewScrollPositionRight animated:NO]; i++; if (i==[Array count]) { i=0; } } } 

Espero que sea útil.