如何使用无限分页制作UICollectionView?

时间:2012-11-27 14:31:41

标签: infinite-scroll uicollectionview scroll-paging

我有一个6页的UICollectionView,启用了分页,还有一个UIPageControl。我想要的是,当我来到最后一页时,如果我向右拖动,UICollectionView将无缝地从第一页重新加载。

- (void)scrollViewDidEndDecelerating:(UIScrollView *)sender
{

// The key is repositioning without animation
if (collectionView.contentOffset.x == 0) {
    // user is scrolling to the left from image 1 to image 10.
    // reposition offset to show image 10 that is on the right in the scroll view
    [collectionView scrollRectToVisible:CGRectMake(collectionView.frame.size.width*(pageControl.currentPage-1),0,collectionView.frame.size.width,collectionView.frame.size.height) animated:NO];
}
else if (collectionView.contentOffset.x == 1600) {
    // user is scrolling to the right from image 10 to image 1.
    // reposition offset to show image 1 that is on the left in the scroll view
    [collectionView scrollRectToVisible:CGRectMake(0,0,collectionView.frame.size.width,collectionView.frame.size.height) animated:NO];

}
pageControlUsed = NO;

}

它不能像我想的那样工作。我该怎么办?

3 个答案:

答案 0 :(得分:2)

这就是我最终为我的UICollectionView(像UIPickerView一样的水平滚动):

@implementation UIInfiniteCollectionView

- (void) recenterIfNecessary {
    CGPoint currentOffset = [self contentOffset];
    CGFloat contentWidth = [self contentSize].width;
    // don't just snap to center, since this might be done in the middle of a drag and not aligned.  Make sure we account for that offset
    CGFloat offset = kCenterOffset - currentOffset.x;
    int delta = -round(offset / kCellSize);
    CGFloat shift = (offset + delta * kCellSize);
    offset += shift;
    CGFloat distanceFromCenter = fabs(offset);

    // don't always recenter, just if we get too far from the center.  Eliza recommends a quarter of the content width
    if (distanceFromCenter > (contentWidth / 4.0)) {
        self.contentOffset = CGPointMake(kCenterOffset, currentOffset.y);
        // move subviews back to make it appear to stay still
        for (UIView *subview in self.subviews) {
            CGPoint center = subview.center;
            center.x += offset;
            subview.center = center;
        }
        // add the offset to the index (unless offset is 0, in which case we'll assume this is the first launch and not a mid-scroll)
        if (currentOffset.x > 0) {
            int delta = -round(offset / kCellSize);
            // MODEL UPDATE GOES HERE
        }
    }
}

- (void) layoutSubviews { // called at every frame of scrolling
    [super layoutSubviews];
    [self recenterIfNecessary];
}

@end

希望这有助于某人。

答案 1 :(得分:1)

我没有使用UICollectionView进行无限滚动,但是在使用UIScrollView进行操作时,首先要将内容偏移(而不是使用scrollRectToVisible)调整到所需的位置。然后,循环浏览滚动条中的每个子视图,并根据用户滚动的方向向右或向左调整它们的坐标。最后,如果任何一个结束超出了你想要的范围,那么将它们移到另一端。他们是关于如何进行无限滚动的非常好的WWDC视频,你可以在这里找到:http://developer.apple.com/videos/wwdc/2012/

答案 2 :(得分:1)

我一直在使用Street Scroller示例为图像创建无限卷轴。这工作正常,直到我想设置pagingEnabled = YES;尝试调整recenterIfNecessary代码并最终意识到它必须匹配我希望在分页停止时可见的子视图的框架的contentOffset.x.这真的无法在recenterIfNecessary中起作用,因为你无法知道它会从layoutSubviews调用。如果你确实调整了它,子视图可能会从你的手指下弹出。我在scrollViewDidEndDecelerating进行调整。到目前为止,我没有遇到快速滚动的问题。即使pagingEnabled为NO,它也会工作并模拟分页,但是看起来更自然。

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    [super scrollViewDidEndDecelerating:scrollView];

    CGPoint currentOffset = [self contentOffset];

    // find the subview that is the closest to the currentOffset.
    CGFloat closestOriginX = 999999;
    UIView *closestView = nil;
    for (UIView *v in self.visibleImageViews) {
        CGPoint origin = [self.imageContainerView convertPoint:v.frame.origin toView:self];
        CGFloat distanceToCurrentOffset = fabs(currentOffset.x - origin.x);
        if (distanceToCurrentOffset <= closestOriginX) {
            closestView = v;
            closestOriginX = distanceToCurrentOffset;
        }
    }

    // found the closest view, now find the correct offset
    CGPoint origin = [self.imageContainerView convertPoint:closestView.frame.origin toView:self];
    CGPoint center = [self.imageContainerView convertPoint:closestView.center toView:self];
    CGFloat offsetX = currentOffset.x - origin.x;

    // adjust the centers of the subviews
    [UIView animateWithDuration:0.1 animations:^{
        for (UIView *v in self.visibleImageViews) {
            v.center = [self convertPoint:CGPointMake(v.center.x+offsetX, center.y) toView:self.imageContainerView];
        }
    }];
}