在UICollectionView中创build慢速滚动到indexPath

我正在一个项目中使用UICollectionView来创build一个“图片报价器”,我在这里宣传一系列的标志。 collectionView是一个项目高,十二个项目,并一次显示两到三个项目(取决于标志的大小可见)。

我想从第一个项目到最后一个缓慢的自动滚动animation,然后重复。

有没有人能够做到这一点? 我可以使用滚动工作

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

但是这太快了!

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

这会产生所需的滚动速度,但只有最后几个单元格在系列中可见。 我怀疑他们(甚至是初始的可见单元格)正在立即出院。

有什么想法吗?

你可以试试这个方法:

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

我使用“1像素偏移”技巧。 以编程方式滚动时,只需将contentOffset.x设置为比应该更多/更less1个像素即可。 这应该是不明显的。 并在完成块设置为实际值。 这样可以避免过早出现细胞出问题并获得平滑的滚动animation;)

这里是滚动到右页的例子(例如从第1页到第2页)。 请注意,在animations:块中,我实际上滚动了一个像素( pageWidth * nextPage - 1 )。 然后我在completion:块中恢复正确的值。

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

你也可以有一个“慢”滚动到你的UICollectionView结束,而不必从indexpath跳转到indexpath。 我在TVOS应用程序上快速创build了一个集合视图:

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

我只是在viewDidLoad()调用autoScroll() ,其余的则自行处理。 滚动的速度由UIView的animation时间决定。 你可以(我没有试过)用0秒添加一个NSTimer,所以你可以在userscroll上使其无效。

对于其他人的发现,我已经更新了Masa的build议,在Swift上工作,我已经介绍了一些简化到最后,所以它更像原来的scrollItemsToIndexPathanimation调用。 在我看来,我有数百个项目,所以稳定的步伐对我来说不是一个select。

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

调整dif和修饰符的值可以调整大多数情况下的持续时间/易用级别。

在.h文件中,声明这个定时器,

 NSTimer *Timer; 

放置这个计时器代码,

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

然后,

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

希望它会有用。