需求如下:
簡單來說就是幾張圖片輪播滾動。
原理:采用UICollectionView的重用機(jī)制和循環(huán)滾動的方式實現(xiàn)圖片的輪播滾動孙技。
可以實現(xiàn)的需求方式有:
1娄徊、本地加載:可以創(chuàng)建不帶標(biāo)題的圖片輪播器
2、網(wǎng)絡(luò)加載:創(chuàng)建帶標(biāo)題的圖片輪播器(支持自定義分頁控件圖標(biāo)顏色的修改)
3冗酿、網(wǎng)絡(luò)加載:創(chuàng)建自定義圖片的pageControlDot的圖片輪播器
{currentPageDotImage,pageDotImage}
需要在項目中: pod 'SDCycleScrollView'
在使用的地方:#import "SDCycleScrollView.h"
注意事項
由于該庫中圖片處理采用了SDWebImage所以需要導(dǎo)入第三方庫SDWebImage
首先我們先看下代碼結(jié)構(gòu):
SDCycleScrollView實現(xiàn)的代碼都放在SDCycleScrollView.m中。
項目中如果想使用并初始化SDCycleScrollView络断,可以使用如下方式:
/** 初始輪播圖(推薦使用) */
+ (instancetype)cycleScrollViewWithFrame:(CGRect)frame delegate:(id<SDCycleScrollViewDelegate>)delegate placeholderImage:(UIImage *)placeholderImage;
+ (instancetype)cycleScrollViewWithFrame:(CGRect)frame imageURLStringsGroup:(NSArray *)imageURLStringsGroup;
/** 本地圖片輪播初始化方式 */
+ (instancetype)cycleScrollViewWithFrame:(CGRect)frame imageNamesGroup:(NSArray *)imageNamesGroup;
/** 本地圖片輪播初始化方式2,infiniteLoop:是否無限循環(huán) */
+ (instancetype)cycleScrollViewWithFrame:(CGRect)frame shouldInfiniteLoop:(BOOL)infiniteLoop imageNamesGroup:(NSArray *)imageNamesGroup;
結(jié)合本次需求裁替,我采用了推薦使用的方式進(jìn)行初始化
UIView *infoView = [[UIView alloc] init];
infoView.backgroundColor = [UIColor whiteColor];
[scrollView addSubview:infoView];
NSArray *imagesURLStrings = [self.model.resources_list valueForKey:@"resource_url"];
SDCycleScrollView *cycleScrollView = [SDCycleScrollView cycleScrollViewWithFrame:CGRectMake(24, 14, kSCREEN_WIDTH - 48 , (kSCREEN_WIDTH - 48) / 327 * 160) delegate:self placeholderImage:[UIImage imageNamed:@"placeholder"]];
cycleScrollView.pageControlAliment = SDCycleScrollViewPageContolAlimentCenter;
cycleScrollView.currentPageDotColor = [UIColor whiteColor];
cycleScrollView.imageURLStringsGroup = imagesURLStrings;
cycleScrollView.autoScrollTimeInterval = 5;
cycleScrollView.currentPageDotColor = [UIColor ZHBlueColor];
cycleScrollView.pageDotColor = [UIColor whiteColor];
cycleScrollView.layer.masksToBounds = YES;
cycleScrollView.layer.cornerRadius = 4;
[infoView addSubview:cycleScrollView];
我看到源代碼中實現(xiàn)自動輪播滾動代碼是這樣子滴
通過創(chuàng)建一個Timer,開啟后加到runloop中,目的是防止滑動工程中出現(xiàn)的卡頓現(xiàn)象貌笨。
- (void)setupTimer
{
[self invalidateTimer]; // 創(chuàng)建定時器前先停止定時器弱判,不然會出現(xiàn)僵尸定時器,導(dǎo)致輪播頻率錯誤锥惋。
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:self.autoScrollTimeInterval target:self selector:@selector(automaticScroll) userInfo:nil repeats:YES];
_timer = timer;
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
}
無線循環(huán)中添加timer的目的是要獲取到當(dāng)前的index昌腰,以及滾動到當(dāng)前的index,作者是這樣實現(xiàn)的:
_totalItemsCount = self.infiniteLoop ? self.imagePathsGroup.count * 100 : self.imagePathsGroup.count;
然后作者創(chuàng)建了count * 100的這樣的一個collectionView,每次都是從中間位置開始輪播膀跌。當(dāng)currentIndex >= _totalItemsCount的時候就會將contentOffset設(shè)置到_totalItemsCount *0.5的位置
- (void)scrollToIndex:(int)targetIndex
{
if (targetIndex >= _totalItemsCount) {
if (self.infiniteLoop) {
targetIndex = _totalItemsCount * 0.5;
[_mainView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:targetIndex inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
}
return;
}
[_mainView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:targetIndex inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:YES];
}
在layoutSubViews方法中作者也實現(xiàn)了類似的方法遭商,初始化的時候就從_totalItemsCount *0.5的位置開始輪播
if (_mainView.contentOffset.x == 0 && _totalItemsCount) {
int targetIndex = 0;
if (self.infiniteLoop) {
targetIndex = _totalItemsCount * 0.5;
}else{
targetIndex = 0;
}
[_mainView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:targetIndex inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
}
并且作者還針對app置于后臺一會后再置于前臺,有可能會出現(xiàn)卡住的現(xiàn)象捅伤。作者在這里添加了一個解決方法:重新設(shè)置_totalItemsCount *0.5的位置開始輪播
#pragma mark - public actions
- (void)adjustWhenControllerViewWillAppera
{
long targetIndex = [self currentIndex];
if (targetIndex < _totalItemsCount) {
[_mainView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:targetIndex inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
}
}
如果需要實現(xiàn)點擊劫流、滾動回調(diào)需要設(shè)置代理,完成相應(yīng)的delegate即可丛忆。
@protocol SDCycleScrollViewDelegate <NSObject>
@optional
/** 點擊圖片回調(diào) */
- (void)cycleScrollView:(SDCycleScrollView *)cycleScrollView didSelectItemAtIndex:(NSInteger)index;
/** 圖片滾動回調(diào) */
- (void)cycleScrollView:(SDCycleScrollView *)cycleScrollView didScrollToIndex:(NSInteger)index;