轮播图使用的场景非常多,一般情况下不会使用到无限轮播。大多数的场景是轮播到最后一张图时强制切换contentOffset,这样最后一张和第一张图过渡就显得不平滑,接下来主要浅析两种实现平滑无限轮播的优化方案。为什么说是优化方案,一般在做广告轮播的时候,不会有太多数目的图片展示需求,也就5张左右,这个时候性能优化没有什么特别需要考虑。一旦数目变大,比如20,那这个时候就需要考虑性能优化
第一种:采用3个UIImageView来实现
这种方式较平时用的有多少图片就初始化多少的imageview实现方式类似,但是我们不会在一开始初始化所有的图片,因为就算全部初始化,那些不显示的图片用户是看不到的,没有必要放那占用着,完全可以在需要展示的时候再初始化。下面是实现思路
整个思路就是初始化scrollview的宽度是5个imageview宽,初始化3个imageview,imageview1显示最后一张图片,imageview2显示第一张图片,imageview2显示第二张图片。然后在每次滑动的时候,动态的去改变这个三个imageview的内容和scrollview的contentOffset,从而达到无限轮播的效果。如下图所示
第二种:采用UICollectionView来实现
UICollectionView想必都不陌生,为什么要用UICollectionView来实现无限轮播图呢?原因是跟UITableView一样,基于系统优化好的复用机制,能让无限轮播得到相当好的资源优化。但是这个无限循环是一个假的无限循环的效果,为什么呢?看下面的实现思路
整个思路就是初始化一个cell数目比较大(比如5000)的UICollectionView,cell就是我们要展示的图片。然后初始化数据源的时候,从最中间一个开始,分别往两边循环设置数据。完成后让UICollectionView显示最中间的cell,这样滑动的时候就有了无限循环的效果。这也就是为什么一开始说是假循环的原因,如果真的遇到了一直滑下去的操作,到最后肯定是滑不动了。如下图所示
#####关键代码实现
UICollectionView的初始化
//自定义UICollectionView风格
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
flowLayout.itemSize = frame.size;
flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
flowLayout.minimumLineSpacing = 0;
self.collectionView = [[UICollectionView alloc] initWithFrame:self.bounds collectionViewLayout:flowLayout];
//设置代理和数据源
self.collectionView.delegate = self;
self.collectionView.dataSource = self;
self.collectionView.showsHorizontalScrollIndicator = NO;
//允许分页
self.collectionView.pagingEnabled = YES;
self.collectionView.backgroundColor = [UIColor lightGrayColor];
[self addSubview:self.collectionView];
//注册cell
[self.collectionView registerClass:[CarouselCell class] forCellWithReuseIdentifier:@"carouselCell"];
数据源设置完毕后让UICollectionView跳转到指定的cell
//设置cell的最大数和默认显示的cell索引
#define TotalRowsInSection (2000 * self.dataSources.count)
#define DefaultRow (NSUInteger)(TotalRowsInSection * 0.5)
[self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:DefaultRow inSection:0] atScrollPosition:UICollectionViewScrollPositionLeft animated:NO];
cell的初始化代理事件
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ID = @"carouselCell";
CarouselCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:ID forIndexPath:indexPath];
if (!cell) {
cell = [[NSBundle mainBundle] loadNibNamed:@"CarouselCell" owner:self options:nil][0];
}
cell.dataModel = self.dataSources[indexPath.item % self.dataSources.count];
return cell;
}
滑动一页之后修改pageControll的当前页码
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
{
NSIndexPath *visiablePath = [[collectionView indexPathsForVisibleItems] firstObject];
//设置pageControl的当前页
self.pageControl.currentPage = visiablePath.item % self.dataSources.count;
}
cell的点击事件
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger index = indexPath.item % self.dataSources.count;
if ([self.delegate respondsToSelector:@selector(clickedAtIndex:)]) {
[self.delegate clickedAtIndex:index];
}
}