因爲項目中使用第三方的輪播圖出現了崩潰狀況,同時也想減小項目的依賴性,因此想本身實現一個輪播圖。實現這樣一個輪播圖,能夠使用UICollectionView
或者UIScrollView
,固然UICollectionView
實現起來更容易一些。ios
實現一個無限循環的輪播圖的主要難點是如何實現左右無限滑動,在知乎上搜的的答案 ios輪播圖實現原理?。git
N張照片把contentsSize
設置爲N+2個圖片的寬度,例子以下,兩端填充如圖,當處於一端時,且即將進入循環狀態的時候,如第二張圖,從狀態1滑動到狀態2,在滑動結束的時候,將當前的位置直接轉到狀態3,直接setContentOffset
神不知鬼不覺,視覺上是循環的。github
用view數組存儲當前須要輪播的內容,直接使用三個指針,分爲左,中,右分別指向數組中的view。屏幕一直顯示的是「中」指向的view。過程以下,以此不停地變換三個指針,實現效果上的輪播。這樣有個缺陷,就是每次僅能滑動一頁,沒辦法快速滑動以滑過兩頁。數組
咱們來看看SDCycleScrollView這個超過4000Star的第三方庫是如何實現的。首先它也是用UICollectionView
來實現的。bash
- (void)setImagePathsGroup:(NSArray *)imagePathsGroup{
_imagePathsGroup = imagePathsGroup;
_totalItemsCount = self.infiniteLoop ? self.imagePathsGroup.count * 100 : self.imagePathsGroup.count;
······
}
複製代碼
它的實現方法比較暴力,直接將將CellIterm
的數量設置爲圖片數量 x 100
,而後:oop
if (self.infiniteLoop) {
targetIndex = _totalItemsCount * 0.5;
[_mainView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:targetIndex inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
}
複製代碼
在初始化運行的時候,將UICollectionView
滑動到CellIterm
數量的中間頁,在左右滑動,當滑動到左右兩端邊界時,再從新滾動到輪播頁中間的位置。ui
綜合比較一下上面👆的三種方法,第一種方法容易理解,並且思路也比較清晰。因此我用第一種方法動手實現了一個輪播圖。spa
首先,設置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時,就不讓其進行滾動。code
- (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];
}
}
}
複製代碼
最終效果以下,支持垂直和水平滾動:
文中的例子能夠到GitHub下載。