前言
由于项目中使用第三方的轮播图出现了崩溃情况,同时也想减少项目的依赖性,所以想自己实现一个轮播图。实现这样一个轮播图,可以使用UICollectionView
或者UIScrollView
,当然UICollectionView
实现起来更容易一些。
原理
实现一个无限循环的轮播图的主要难点是如何实现左右无限滑动,在知乎上搜的的答案 ios轮播图实现原理?。
1.方案一
N张照片把contentsSize
设置为N+2个图片的宽度,例子如下,两端填充如图,当处于一端时,且即将进入循环状态的时候,如第二张图,从状态1滑动到状态2,在滑动结束的时候,将当前的位置直接转到状态3,直接setContentOffset
神不知鬼不觉,视觉上是循环的。
2.方案二
用view数组存储当前需要轮播的内容,直接使用三个指针,分为左,中,右分别指向数组中的view。屏幕一直显示的是“中”指向的view。过程如下,以此不停地变换三个指针,实现效果上的轮播。这样有个缺陷,就是每次仅能滑动一页,没办法快速滑动以滑过两页。
方案二.jpg3.方案三
我们来看看SDCycleScrollView这个超过4000Star的第三方库是如何实现的。首先它也是用UICollectionView
来实现的。
- (void)setImagePathsGroup:(NSArray *)imagePathsGroup{
_imagePathsGroup = imagePathsGroup;
_totalItemsCount = self.infiniteLoop ? self.imagePathsGroup.count * 100 : self.imagePathsGroup.count;
······
}
它的实现方法比较暴力,直接将将CellIterm
的数量设置为图片数量 x 100
,然后:
if (self.infiniteLoop) {
targetIndex = _totalItemsCount * 0.5;
[_mainView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:targetIndex inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
}
在初始化运行的时候,将UICollectionView
滑动到CellIterm
数量的中间页,在左右滑动,当滑动到左右两端边界时,再重新滚动到轮播页中间的位置。
动手实现
综合比较一下上面👆的三种方法,第一种方法容易理解,而且思路也比较清晰。所以我用第一种方法动手实现了一个轮播图。
首先,设置iterm
的数量为self.imageArray.count + 2
。
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
/**只有是无限循环和数组个数大于1时,才能无限循环*/
if (self.isinFiniteLoop && self.imageArray.count > 1) {
return self.imageArray.count + 2;
}else{
return self.imageArray.count;
}
}
然后,在下面👇的赋值部分,当支持无限轮播,并且图片数量大于1时,将UICollectionView
滚动到第一个index
,如果图片数量小于等于1时,就不让其进行滚动。
- (void)setImageArray:(NSArray *)imageArray{
······
if (_imageArray.count > 1) {
_myCollection.scrollEnabled = YES;
[self setIsAutoScroll:_isAutoScroll];
}else{
_myCollection.scrollEnabled = NO;
[self setIsAutoScroll:NO];
}
[_myCollection reloadData];
if (_isinFiniteLoop && _imageArray.count > 1) {
[_myCollection scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:1 inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
}
}
在滑动结束的时候,如果处在临界状态,当前索引是0
时,就滑动到索引是self.imageArray.count
的位置,当前索引是currentIndex == self.imageArray.count + 1
时,就滑动到索引是0
的位置。
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView{
NSInteger currentIndex = [self currentIndex];
if (self.isinFiniteLoop && self.imageArray.count > 1) {
if (currentIndex == 0) {
[_myCollection scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:self.imageArray.count inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
}else if (currentIndex == self.imageArray.count + 1){
[_myCollection scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:1 inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
}
}
}
最终效果如下,支持垂直和水平滚动:
无限轮播图.gif
文中的例子可以到GitHub下载。
网友评论