用 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