图片无限滚动

用 UICollectionView 和 NSTimer 实现图片的无限滚动播放效果.
效果图如:
无限滚动

实现思路:
(1) 首先在控制器中添加 UICollectionView 根据模型的个数显示模型数据(流水布局,自定义 UICollectionViewCell 显示模型数据)
(2) 如果仅仅只有一组数据, 当滚动到最后一个位置的时候,这个时候,由于已经到了最后一个,所以定时器如果再次滚动就会出现越界情况.
解决方法有两个,一个是定义一个可变数组,添加多次同样的模型,但是这样内存较大.

//视图模型类为: Newes
//自定义cell类为: ImageCell
#define XCMaxSections 10
- (NSMutableArray *)newses
{
    if (_newses == nil) {
        self.newses = [NSMutableArray array];
        for (int i = 0; i<200; i++) {
            NSArray *array = [Newes objectArrayWithFilename:@"newses.plist"];
            [self.newses addObjectsFromArray:array];
        }
    }
    return _newses;
}

第二个是定义多组,定时器每次执行的时候,首先将UICollectionView滚动到中间的那组,然后,继续向后滚动,这样就永远不会出现越界的情况. 同时在控制器显示的时候,将UICollectionView滚动到中间的一组,这样显示图片的前后,都会有图片组.
代码

/**
 *  控制器显示的时候
 */
- (void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];

    //在控制器显示的时候, 跳转到中间的那组
    NSIndexPath *beginIndexPath = [NSIndexPath indexPathForItem:0 inSection:XCMaxSections/2];
    [self.collectionView scrollToItemAtIndexPath:beginIndexPath atScrollPosition:UICollectionViewScrollPositionLeft animated:NO];
}

/**
 *  添加定时器
 */
- (void)addTimer{
    //添加定时器
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(nextImage) userInfo:nil repeats:YES];
    [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
}

/**
 *  定时器方法:下一张图片
 */
- (void)nextImage{

    //当前正在展示的位置
    NSIndexPath *currentIndexPath = [[self.collectionView indexPathsForVisibleItems] lastObject];

    NSIndexPath *resetIndexPath = [NSIndexPath indexPathForItem:currentIndexPath.item inSection:XCMaxSections/2];
    [self.collectionView scrollToItemAtIndexPath:resetIndexPath atScrollPosition:UICollectionViewScrollPositionLeft animated:NO];

    //计算出下一个位置
    NSInteger nextItem = resetIndexPath.item + 1;
    NSInteger nextSection = resetIndexPath.section;
    if (nextItem == self.newesArr.count) {
        nextItem = 0;
        nextSection += 1;
    }
    //设置pageControl选中的页码
    self.pageControl.currentPage = nextItem;

    NSIndexPath *nextIndexPath = [NSIndexPath indexPathForItem:nextItem inSection:nextSection];

    //滚动到下一个位置
    [self.collectionView scrollToItemAtIndexPath:nextIndexPath atScrollPosition:UICollectionViewScrollPositionLeft animated:YES];  
}

(3) 当用户拖拽视图的时候, 应该将定时器移除, 当停止拖拽的时候, 再将定时器重新添加

/**
 *  销毁定时器
 */
- (void)clearTimer{
    if ([self.timer isValid]) {
        [self.timer invalidate];
        self.timer = nil;
    }
}

#pragma mark - UICollectionViewDelegate
/**
 *  即将拖拽
 */
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
    [self clearTimer];
}
/**
 *  停止拖拽
 */
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
    [self addTimer];
}

/**
 *  停止滚动:重新计算 PageControl 显示的页码
 */
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
    int page = (int)(self.collectionView.contentOffset.x / self.collectionView.bounds.size.width) % self.newesArr.count;
    self.pageControl.currentPage = page;
}

添加UICollectionView 和 UIPageControl 的代码如下:

/**
 *  懒加载数据模型
 */
- (NSArray *)newesArr{
    if (_newesArr == nil) {
        _newesArr = [Newes objectArrayWithFilename:@"newses.plist"];
    }
    return _newesArr;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];

    //添加CollectionView
    [self addCollectionView];

    [self addTimer];
}

/**
 *  添加CollectionView 和 UIPageControl
 */
- (void)addCollectionView{

    // 1 添加UICollectionView
    UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
    //设置各行的间距为0
    flowLayout.minimumLineSpacing = 0;
    //设置滚动方向(水平)
    flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;

    //设置每个item的尺寸
    CGFloat itemWidth = [UIScreen mainScreen].bounds.size.width - 2 * magin;
    flowLayout.itemSize = CGSizeMake(itemWidth, CollectionHeight);

    UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:flowLayout];
    collectionView.backgroundColor = [UIColor blueColor];
    //设置代理和数据源方法
    collectionView.dataSource = self;
    collectionView.delegate = self;
    //隐藏滑动条
    collectionView.showsHorizontalScrollIndicator = NO;
    //设置分页
    collectionView.pagingEnabled = YES;

    [self.view addSubview:collectionView];
    self.collectionView = collectionView;

    //注册cell
    [collectionView registerClass:[ImageCell class] forCellWithReuseIdentifier:ID];

    //自动布局
    collectionView.sd_layout.leftSpaceToView(self.view, magin).rightSpaceToView(self.view, magin).topSpaceToView(self.view, 40).heightIs(CollectionHeight);

    // 2 添加分页控制器PageControl
    UIPageControl *pageControl = [[UIPageControl alloc] init];
    //设置页数
    pageControl.numberOfPages = self.newesArr.count;
    //设置选中页数的颜色
    pageControl.currentPageIndicatorTintColor = [UIColor redColor];
    //设置其他未选中页数的颜色
    pageControl.pageIndicatorTintColor = [UIColor whiteColor];

    [self.view addSubview:pageControl];
    self.pageControl = pageControl;

    //设置尺寸
    pageControl.sd_layout.rightSpaceToView(self.view, 70).bottomEqualToView(collectionView).widthIs(50).heightIs(37); 
}

#pragma mark - UICollectionViewDataSource
/**
 *  多少组
 */
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
    return XCMaxSections;
}

/**
 *  每组多少个数据
 */
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
    return self.newesArr.count;
}


- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{

    ImageCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:ID forIndexPath:indexPath];
    cell.newes = self.newesArr[indexPath.item];

    return cell;
}

更详细的代码:(如 Newes 和 ImageCell的代码见 github )
github

不积跬步,无以至千里;不积小流,无以成江海。
原文地址:https://www.cnblogs.com/xiaocai-ios/p/7779793.html