example collection ios scroll uiviewanimation nsindexpath uicollectionview

ios - example - uicollectionviewcell indexpath



Creación de desplazamiento lento a indexPath en UICollectionView (5)

Estoy trabajando en un proyecto en el que utilizo un UICollectionView para crear un "ticker de imagen" en el que estoy anunciando una serie de logotipos. El collectionView tiene un elemento alto y doce elementos, y muestra de dos a tres elementos a la vez (dependiendo del tamaño de los logotipos visibles).

Me gustaría hacer una animación de desplazamiento automático lento desde el primer elemento hasta el último, y luego repetir.

¿Alguien ha podido hacer este trabajo? Puedo obtener el desplazamiento de trabajo 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) se están eliminando de inmediato.

¿Alguna idea?


En el archivo .h, declare este temporizador,

NSTimer *Timer;

Coloque este código de temporizador,

[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 de utilidad.


Para cualquier 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 para que se parezca más a la llamada animada scrollItemsToIndexPath original. Tengo cientos de artículos en mi opinión, por lo que un ritmo constante no era 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: "scrollTimerTriggered:", userInfo: nil, repeats: true) } func scrollTimerTriggered(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.


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


También puede tener un desplazamiento "lento" hasta el final de su UICollectionView sin tener que "saltar" de la ruta de índice a la de índice. TVOS esto rápidamente para una vista de colección en una aplicación de 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 resto se encarga de ello. La velocidad del desplazamiento se decide por el tiempo de animación de la vista UIView . Podrías (no lo he intentado) agregar un NSTimer con 0 segundos en su lugar para que puedas invalidar el desplazamiento de los usuarios.


Yo uso un truco de "1 píxel de desplazamiento" . Cuando se desplaza programáticamente, simplemente configure el contentOffset.x final en 1 píxel más / menos de lo que debería. Esto debería ser imperceptible. Y en el bloque de finalización establecerlo en valor real. De esa manera, puede evitar el problema de la eliminación de celdas prematura y obtener una animación de desplazamiento suave;)

Este es un ejemplo de desplazamiento a la página de la derecha (por ejemplo, de la página 1 a 2). Observe que en las animations: bloque, realmente me pageWidth * nextPage - 1 un píxel menos ( pageWidth * nextPage - 1 ). Entonces restauro el valor correcto en la completion: bloque.

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)]; }];