CollectionView 無限輪播設計思路

老JI發表於2018-01-11

 原來用scrollview實現過無限輪播,每張輪播圖是UIImageView ,有頁碼,有標題,用scrollView實現起來比較簡單。但是最近遇到一個需求 。每個輪播圖上有好幾個頭像和按鈕,用目前專案中用scrollView實現的輪播 圖實現不了,或者說改動比較大。於是就想著用collectionView實現。當時的 初步構想就是每張輪播圖就是一個自定義的cell ,這樣就比較簡單了。 在沒開始之前先在在網上找了一下,好多demo實現的方式都是一樣的,就是把dataSource設為一個很大的數字,建立n多個cell,用來達到無限。。。按道理,先不說效能如何,就是設為比較大的數字,在理論上該數字也是有限的!並不是無限輪播~~~

我的大致設計思路如下:

1,定時器。用於在固定的間隔滾動一頁
2,collectionView,自定義一個cell用於輪播展示
3,對collectionView的資料來源A進行處理。新建一個陣列B,把A陣列的最後一個新增到B陣列的第一個,把A陣列的第一個新增到B陣列的最後一個。這樣B陣列中就比源陣列A多了兩個資料。在(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section 中返回的是陣列B的長度
4, 在scrollview的相關代理方法中處理相應人為拖動操作和滾動
複製程式碼

下面結合程式碼來說每步的具體實現。

1> 每隔固定的時間呼叫此方法實現滾動

- (void)startScrollAutomtically { // 每次加 self.bounds.size.width 寬度
    [self setContentOffset:CGPointMake(self.contentOffset.x + self.bounds.size.width, self.contentOffset.y) animated:YES];
}
複製程式碼

2> 對資料來源進行處理 如果原始資料來源的長度大於一個則啟動定時器,反之不啟動定時器。如果原始資料來源的長度大於一個則需要處理資料來源,即上面3所說的。另外重新整理完資料來源則預設滾動到第一頁

- (void)configWithData:(NSArray<id<JWCBannerDataProtocol>> *)datas {
    if (_originalData.count > 1) {
        NSMutableArray *tempArr = [[NSMutableArray alloc] initWithArray:_originalData];
        [tempArr insertObject:[_originalData lastObject] atIndex:0];
        [tempArr addObject:[_originalData firstObject]];
        self.customData = tempArr.copy;
        dispatch_async(dispatch_get_main_queue(), ^{
            [self scrollToPage:1 animated:YES];
        });
        [self startTimer];
        self.isOnlyOne = NO;
    } else {
        self.customData = _originalData.copy;
        [self stopTimer];
        self.isOnlyOne = YES;
        self.currentIndex = 0;
    }
}



複製程式碼

3> scrollView的幾個代理方法

// 將要開始拖拽 停止定時器
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
    [self stopTimer];
}
// 將要停止拖拽 開始定時器
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
    if (_originalData.count > 1) { //如果資料來源大於1 才啟動定時器
        [self startTimer];
    }
}
// 停止拖動
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    [self checkPageIndx];
}
// 動畫停止
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
    [self checkPageIndx];
}

複製程式碼

// 此方法是人為拖動完成需要做的處理

- (void)checkPageIndx {
    //當滾動到最後一張圖片時,繼續滾向後動跳到page 1
    if (self.contentOffset.x >= (self.customData.count - 1) * self.bounds.size.width) {
        [self scrollToPage:1 animated:NO];
    }
    //當滾動到第一張圖片時,繼續向前滾動跳到倒數第二
    if (self.contentOffset.x < 0) {
        [self scrollToPage:self.customData.count - 2 animated:NO];
    }
}
複製程式碼

// 停止滾動 計算當前的index 此方法是無論人為還是自動改變scrollview的 offset 都會呼叫此方法 所以在此方法中計算當前的index 這個index可用於顯示頁碼

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    CGFloat width = self.frame.size.width;
    NSInteger index = (scrollView.contentOffset.x + width * 0.5 ) / width;
    if (index == 0) {
        index = _originalData.count - 1;
    } else if (index >= _customData.count - 1) {
        index = 0;
    } else {
        index = index - 1;
    }
    self.currentIndex = index;
}
複製程式碼

轉載請註明出處:https://juejin.im/post/5a55d5e2518825692262f258 謝謝!

以上只是寫了大致的思路,具體的實現程式碼在Git

符效果圖

CollectionView 無限輪播設計思路
)

相關文章