我已经通过几个解决方案检查了UICollectionView
中无限滚动的问题,但它们都没有完美运行(1,2,3甚至是教程 - 4)。
主要问题在于UICollectionView
包含图像。当我滚动到第一个或最后一个项目(使它无限)时,在它们加载之前我可以看到一个非常短的'眨眼'必须被删除。我不知道如何解决它,欢迎任何帮助。
我应该提一下,我正在制作的图库不应该允许任何用户互动,它应该自己滚动(演示文稿可以说)。
我尝试过两种最有趣的方法:
方法1:collectionView中的14个项目,按顺序排列:@ [8,9,@ [0-9],0,1](所以8,9,1,2重复)
// a timer to move everything
_timer = [NSTimer scheduledTimerWithTimeInterval:0.02f target:self selector:@selector(scroll) userInfo:nil repeats:YES];
// timer selector
- (void)scroll {
self.collectionView.contentOffset = CGPointMake(self.collectionView.contentOffset.x+1, self.collectionView.contentOffset.y);
}
// check if we need to change offset
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"something" forIndexPath:indexPath];
if ([self scrollProperly]) {
// return cell;
}
}
// method to check & set proper offset (author: D33pN16h7)
- (BOOL)scrollProperly {
// check if near the end or beginning
BOOL test = NO;
CGFloat currentOffsetX = self.collectionView.contentOffset.x;
CGFloat currentOffSetY = self.collectionView.contentOffset.y;
CGFloat contentWidth = self.collectionView.contentSize.width;
if (currentOffsetX < (contentWidth / 6.0f)) {
self.collectionView.contentOffset = CGPointMake((currentOffsetX + (contentWidth/2)), currentOffSetY);
test = YES;
}
if (currentOffsetX > ((contentWidth * 4)/ 6.0f)) {
self.collectionView.contentOffset = CGPointMake((currentOffsetX - (contentWidth/2)), currentOffSetY);
test = YES;
}
return test;
}
第二种方法:collectionView中的20个项目,按顺序排列:@ [@ [0-9],@ [0-9]](因此整个数组是重复的)。还有定时器,在以前的方法中也是如此。我们不是在[self scrollProperly]
中运行collectionView:cellForItemAtIndexPath:
,而是使用:
if (indexPath.row == 2) {
[collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:([collectionView numberOfItemsInSection:indexPath.section] - 3) inSection:indexPath.section] atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
} else if (indexPath.row == ([collectionView numberOfItemsInSection:indexPath.section] - 1)) {
[collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:indexPath.section] atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
}
答案 0 :(得分:1)
好吧,我的最终解决方案是让滚动很长 - 在collectionView:cellForItemAtIndexPath:
我正在从我的数据库中读取其大小的模数。在collectionView:numberOfItemsInSection:
中,有一个恒定的大小。当我达到恒定大小时,我滚动到第一行。因为我已经制作了恒定大小,所以大量闪烁不会刺激用户,而且滚动实际上是无限的。解决方案并不完美,但我不知道如何解决它。
答案 1 :(得分:1)
我知道这有点晚了但我想出了如何实现一个无限可滚动的UICollectionView;
根据细胞的布局方式,这部分可能会有所不同,但基本上它会分解为这些步骤。
1)修改数据源并在数据阵列的正面和背面复制所需的单元格。
例如,如果您的数据源数组如下所示:
NSArray* array = @[@1, @2, @3, @4, @5];
让我们说它们各自占据视图高度的1/5,你可能希望修改你的数组看起来像这样:
NSArray* array = @[@4, @5, @1, @2, @3, @4, @5, @1, @2, @3];
通过这种方式,你的集合视图基本上是“重复”那些单元格,以给出它继续前进的错觉。
这部分是最难的,因为你修改数据阵列的方式取决于一次在屏幕上适合多少个单元格。如果一次只有一个单元格适合屏幕并且数据数组为@[@1, @2, @3]
,则可以轻松将其修改为@[@3, @1, @2, @3, @1];
(这是this awesome tutorial中的示例。
那我们为什么要这样做呢?这是因为collectionview需要滚动到的东西,即集合视图正面和背面的额外填充。
2)使用键值观察以观察collectionView的contentOffset。
[self.collectionView addObserver:self forKeyPath:@"contentOffset" options:0 context:NULL];
3)检查contentOffset是否已达到优势。
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
CGFloat offset = self.collectionView.contentOffset.y;
if(offset <= 1){
[self.collectionView setContentOffset:CGPointMake(0, self.collectionView.height-2)];
[self.collectionView reloadData];
}else if(offset >= self.collectionView.height-1){
[self.collectionView setContentOffset:CGPointMake(0, 2)];
[self.collectionView reloadData]; //call to reload the now visible cells, ensure delegate gets called
}
}
如果contentOffset在顶部边缘的几个像素内,则设置contentOffset,以便集合视图在用户不知道的情况下以静默方式向下滚动页面。当contentOffset到达另一边时,执行相同的操作。
两件非常重要的事情。
1)首次初始化collectionView时,将contentOffset设置为(0,3)。这样,它就会触发KVO方法中的if语句。 2)在KVO方法中设置contentOffset时,还要确保在调用方法时,您设置的点不会触发if语句。
请记住,因为您正在观察contentOffset,所以设置contentOffset会立即触发该方法!只要它没有第二次设置contentOffset,从而导致无限循环的更改通知,你应该没问题。
另请不要忘记将collectionView.bounces
设置为YES
。