原來用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
符效果圖
)