我正在使用UICollectionView创建一个“图像行情指示器”的项目,在该项目中我要宣传一系列徽标。 collectionView高一个项目,长十二个项目,并且一次显示两到三项(取决于可见徽标的大小)。
我想从第一项到最后一项缓慢地自动滚动动画,然后重复。
有人能完成这项工作吗?我可以使用
进行滚动工作[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
设置为比其应多/少1个像素。这应该是不明显的。并在完成块中将其设置为实际值。这样,您可以避免过早的单元出队问题,并获得平滑的滚动动画;)
这里是滚动到右页(例如从第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
末尾,而不必从索引路径“跳转”到索引路径。我为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()
}
}
[我只是称呼autoScroll()
中的viewDidLoad()
,其余的由它自己处理。滚动的速度由UIView
的动画时间决定。您可以(我没有尝试过)用0
秒添加NSTimer,以便可以在userscroll上使它无效。
对于其他发现此问题的人,我已经更新了Masa的建议以在Swift上运行,并且在结尾处引入了一些缓和,因此它的行为更像原始的scrollItemsToIndexPath动画调用。我认为有数百种物品,因此无法选择稳定的速度。
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;
}
}
}
希望它会有用。
我编写了一个自动滚动的集合视图原型,可以完成您想要的工作。我已经使用计时器进行更新。该集合是圆形的,就像股票行情记录器一样。诚然,我不确定这是否是在iOS上执行此操作的最佳方法:https://github.com/jmorin927/inifiniteScroll