對於圖像輪播框架的實現,網上有很多種方法,可以使用UIScrollView,也可以使用UICollectionView。
今天就撸一波代碼,打算使用3個UIImageView實現,這樣比較節省內存(個人偏向於這個方案),當然由於UICollectionView的Cell有復用機制,也比較好。
思路:1)在UIScrollView上面添加3個UIImageView,分別為leftImageView,centerImageView,RightImageView
2)UIScrollView初始化時,contentOffset停留在中間的UIImageView
3)使用一個定時器,定時器觸發是,把contentOffset從中間通過動畫滑動到第三個UIImageView的位置
4)滑動完成時候,要進行最關鍵的復位操作,就是迅速把contentOffset切換回第二個UIImageView的位置,但是切換前,先centerImageView.image = rightjImageView.image,注意,這裡不適用動畫,所以用戶看不出來切換了
5)下次定時器觸發時,又把contentOffset從第二個位置通過動畫滑動到第三個位置
6)事實上2個UIImageView就可以實現,但是左邊一直有一個提供用戶手動向左滑動
不費話了,貼代碼:
頭文件:
// // CHRDanTangHeaderScrollView.h // test // // Created by Chen Heren on 16/10/12. // Copyright (c) 2016年 Chen Heren. All rights reserved. // #import@class CHRDanTangHeaderScrollView; @protocol CHRDanTangHeaderScrollViewDelegate -(void)DanTangHeaderScrollView:(CHRDanTangHeaderScrollView *)scrollView selectedAt:(NSInteger)index; @end @interface CHRDanTangHeaderScrollView : UIView @property (strong, nonatomic) NSArray *imageUrls; @property (nonatomic) CGFloat intervalTime; @property (weak, nonatomic) id delegate; -(instancetype)initWithFrame:(CGRect)frame ImageUrls:(NSArray *)imageUrls IntervalTime:(CGFloat)intervalTime; @end
源文件:
// // CHRDanTangHeaderScrollView.m // 采用3個UIImageView實現循環顯示 // 思路:暗渡陳倉 // 定時器Fire時,正常進行滑動,待滑動完成,重新把視圖contentoffset恢復到中間uiimageview的狀態 // Created by Chen Heren on 16/10/12. // Copyright (c) 2016年 Chen Heren. All rights reserved. // #import "CHRDanTangHeaderScrollView.h" #import "UIImageView+WebCache.h" @interface CHRDanTangHeaderScrollView () ///滑動視圖 @property (strong, nonatomic) UIScrollView *scrollView; ///指示器 @property (strong, nonatomic) UIPageControl *pageControl; ///左UIImageView @property (strong, nonatomic) UIImageView *leftImageView; ///中間UIImageView @property (strong, nonatomic) UIImageView *centerImageView; ///右UIImageView @property (strong, nonatomic) UIImageView *rightImageView; @property (nonatomic) NSInteger currentPage; @property (strong, nonatomic) NSTimer *timer; @end @implementation CHRDanTangHeaderScrollView -(instancetype)initWithFrame:(CGRect)frame ImageUrls:(NSArray *)imageUrls IntervalTime:(CGFloat)intervalTime{ self = [self initWithFrame:frame]; if (self) { self.imageUrls = [NSArray arrayWithArray:imageUrls]; self.intervalTime = intervalTime; self.currentPage = 0; [self setupUI]; } return self; } -(void)setupUI{ [self addSubview:self.scrollView]; [self addSubview:self.pageControl]; [self setupImageView]; [self setupTimer]; } -(UIScrollView *)scrollView{ if (_scrollView == nil) { _scrollView = [[UIScrollView alloc]initWithFrame:self.bounds]; _scrollView.contentSize = CGSizeMake(CGRectGetWidth(self.scrollView.frame) * 3, CGRectGetHeight(self.scrollView.frame)); _scrollView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0); _scrollView.delegate = self; _scrollView.pagingEnabled = YES; _scrollView.showsHorizontalScrollIndicator = NO; _scrollView.decelerationRate = 1.0; _scrollView.contentOffset = CGPointMake(CGRectGetWidth(self.scrollView.frame), 0); } return _scrollView; } -(UIPageControl *)pageControl{ if (_pageControl == nil) { _pageControl = [[UIPageControl alloc]initWithFrame:CGRectMake(self.frame.size.width/2-50, self.frame.size.height-35, 100, 30)]; _pageControl.numberOfPages = self.imageUrls.count; _pageControl.currentPageIndicatorTintColor = [UIColor whiteColor]; _pageControl.pageIndicatorTintColor = [UIColor lightGrayColor]; } return _pageControl; } -(void)setupImageView{ self.leftImageView = [[UIImageView alloc]initWithFrame:CGRectMake(self.frame.size.width *0, 0, self.frame.size.width, self.frame.size.height)]; self.centerImageView = [[UIImageView alloc]initWithFrame:CGRectMake(self.frame.size.width *1, 0, self.frame.size.width, self.frame.size.height)]; self.rightImageView = [[UIImageView alloc]initWithFrame:CGRectMake(self.frame.size.width *2, 0, self.frame.size.width, self.frame.size.height)]; [self.leftImageView sd_setImageWithURL:[self getImageUrlBeforeIndex:self.currentPage]]; [self.centerImageView sd_setImageWithURL:[self getImageUrlAtIndex:self.currentPage]]; [self.rightImageView sd_setImageWithURL:[self getImageUrlAfterIndex:self.currentPage]]; self.leftImageView.contentMode = UIViewContentModeScaleAspectFit; self.centerImageView.contentMode = UIViewContentModeScaleAspectFit; self.rightImageView.contentMode = UIViewContentModeScaleAspectFit; ///用戶看到的只有中間視圖,所以為了簡單起見,只需要添加中間視圖的點擊響應 UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(imageViewTap)]; self.centerImageView.userInteractionEnabled = YES; [self.centerImageView addGestureRecognizer:tap]; [self.scrollView addSubview:self.leftImageView]; [self.scrollView addSubview:self.centerImageView]; [self.scrollView addSubview:self.rightImageView]; } -(void)setupTimer{ self.timer = [NSTimer timerWithTimeInterval:self.intervalTime target:self selector:@selector(timerTick) userInfo:nil repeats:YES]; [[NSRunLoop mainRunLoop]addTimer:_timer forMode:NSRunLoopCommonModes]; } -(void)timerTick{ self.currentPage++; if (self.currentPage == self.imageUrls.count) { self.currentPage = 0; } ///此處設置動畫的時間一定要小於滑動的時間 [UIView animateWithDuration:1 animations:^{ ///動畫發生的滑動 self.centerImageView.userInteractionEnabled =NO; self.scrollView.contentOffset =CGPointMake(CGRectGetWidth(self.scrollView.frame) * 2, 0); } completion:^(BOOL finished) { ///滑動完成後,把當前現實的imageview重現移動回中間位置,此處不能使用動畫,用戶感覺不到 ///移動前,先把中間imageview的image設置成當前現實的iamge self.centerImageView.userInteractionEnabled = YES; self.leftImageView.image = self.centerImageView.image; self.centerImageView.image = self.rightImageView.image; self.scrollView.contentOffset =CGPointMake(CGRectGetWidth(self.scrollView.frame) * 1, 0); [self.rightImageView sd_setImageWithURL:[self getImageUrlAfterIndex:self.currentPage]]; self.pageControl.currentPage = self.currentPage; }]; } #pragma mark - 用戶點擊 -(void)imageViewTap{ NSLog(@"tap at :%ld",self.currentPage); [self.delegate DanTangHeaderScrollView:self selectedAt:self.currentPage]; } #pragma mark - 循環獲取URL -(NSURL *)getImageUrlBeforeIndex:(NSInteger)index{ if (index == 0) { return [self.imageUrls lastObject]; }else{ return self.imageUrls[index-1]; } } -(NSURL *)getImageUrlAfterIndex:(NSInteger)index{ if (index == (self.imageUrls.count - 1)) { return [self.imageUrls firstObject]; }else{ return self.imageUrls[index+1]; } } -(NSURL *)getImageUrlAtIndex:(NSInteger)index{ if (index<0 || index >= self.imageUrls.count) { return nil; }else{ return self.imageUrls[index]; } } #pragma mark - scrollView滑動事件 -(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{ ///有用戶手動拖動,則停止定時器 [self.timer invalidate]; } -(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{ ///用戶滑動停止,重新啟動定時器 [self setupTimer]; } -(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{ NSInteger index = scrollView.contentOffset.x/scrollView.frame.size.width; if (index ==0) { //向左滑動 self.currentPage--; if (self.currentPage <0 ) { self.currentPage = self.imageUrls.count; } self.rightImageView.image = self.centerImageView.image; self.centerImageView.image = self.leftImageView.image; scrollView.contentOffset = CGPointMake(CGRectGetWidth(self.scrollView.frame) * 1, 0); [self.leftImageView sd_setImageWithURL:[self getImageUrlBeforeIndex:self.currentPage]]; self.pageControl.currentPage = self.currentPage; }else if(index == 2){ ///向右滑動 self.currentPage++; if (self.currentPage ==self.imageUrls.count ) { self.currentPage = 0; } self.leftImageView.image = self.centerImageView.image; self.centerImageView.image = self.rightImageView.image; scrollView.contentOffset = CGPointMake(CGRectGetWidth(self.scrollView.frame) * 1, 0); [self.rightImageView sd_setImageWithURL:[self getImageUrlAfterIndex:self.currentPage]]; self.pageControl.currentPage = self.currentPage; } ///沒有滑動一頁 } @end
#import "ViewController.h" #import "CHRDanTangHeaderScrollView.h" @interface ViewController ()@end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. NSURL *url = [[NSBundle mainBundle]URLForResource:@"1" withExtension:@".png"]; NSURL *ur2 = [[NSBundle mainBundle]URLForResource:@"2" withExtension:@".png"]; NSURL *ur3 = [[NSBundle mainBundle]URLForResource:@"3" withExtension:@".png"]; NSURL *ur4 = [[NSBundle mainBundle]URLForResource:@"4" withExtension:@".png"]; CHRDanTangHeaderScrollView *scrollView = [[CHRDanTangHeaderScrollView alloc]initWithFrame:CGRectMake(0, 100, self.view.frame.size.width, 200) ImageUrls:@[url,ur2,ur3,ur4] IntervalTime:2]; scrollView.delegate = self; [self.view addSubview:scrollView]; } -(void)DanTangHeaderScrollView:(CHRDanTangHeaderScrollView *)scrollView selectedAt:(NSInteger)index{ NSLog(@"%ld",index); } @end
demo傳送門:https://git.oschina.net/heren/CHRScrollView.git