如何實現一個無限循環的輪播圖

前言

因爲項目中使用第三方的輪播圖出現了崩潰狀況,同時也想減小項目的依賴性,因此想本身實現一個輪播圖。實現這樣一個輪播圖,能夠使用UICollectionView或者UIScrollView,固然UICollectionView實現起來更容易一些。ios

原理

實現一個無限循環的輪播圖的主要難點是如何實現左右無限滑動,在知乎上搜的的答案 ios輪播圖實現原理?git

1.方案一

N張照片把contentsSize設置爲N+2個圖片的寬度,例子以下,兩端填充如圖,當處於一端時,且即將進入循環狀態的時候,如第二張圖,從狀態1滑動到狀態2,在滑動結束的時候,將當前的位置直接轉到狀態3,直接setContentOffset神不知鬼不覺,視覺上是循環的。github

方案一.jpg

2.方案二

用view數組存儲當前須要輪播的內容,直接使用三個指針,分爲左,中,右分別指向數組中的view。屏幕一直顯示的是「中」指向的view。過程以下,以此不停地變換三個指針,實現效果上的輪播。這樣有個缺陷,就是每次僅能滑動一頁,沒辦法快速滑動以滑過兩頁。數組

方案二.jpg

3.方案三

咱們來看看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];
        }
    }
}
複製代碼

最終效果以下,支持垂直和水平滾動:

無限輪播圖.gif

文中的例子能夠到GitHub下載

相關文章
相關標籤/搜索