轉載自 http://www.jianshu.com/p/aa73c273baf2數組
咱們會常常用到循環滾動圖片,包括定時滾動,點擊觸發事件。
之前所知道的循環滾動圖片的方法是這樣的。好比:一共5張圖片,位置爲1,2,3,4,5。網絡
imageView
。scrollViewDidScroll
的代理方法裏面判斷scrollView.contentOffset.x>320*6-1
,將scrollView
的偏移量設置爲320
的位置,動畫設置爲NO
。320*6
,這個值是大於320*6-1
的,進入到if
語句,將scrollView
設置320
的位置,則就是第一個圖片1的位置,這樣就形成一個視覺差,是從最後一張圖片滾動到第一張圖片的。之前是那麼用的,可是後來以爲這樣比較佔資源,也比較麻煩,如今是這樣的,無論多少張圖片只建立3個imageView
。app
viewController
中取到圖片數據源,建立當前須要展現的圖片數組長度是3,當前展現的圖片位置默認是0。320
,滑動到下一張圖片的時候,設置當前位置爲1,設置當前數組圖片爲圖片一、圖片二、圖片3,刷新UI,而且把scrollView
的偏移量設置爲320
,即展現的圖片永遠在中間。#import <UIKit/UIKit.h> @protocol CycleScrollViewDelegate; @interface CycleScrollView : UIView<UIScrollViewDelegate>
數據源ide
@property (nonatomic, strong) NSArray *imageArray;
滾動視圖。原本是不須要這個屬性的,可是有個問題:若是圖片正好滾動了一半app進入到後臺,再次打開的時候是滾動到一半狀態,滾動到下一張圖片的時候就行了,因此把這個問題在viewController
裏面處理。oop
@property (nonatomic, strong) UIScrollView *scrollView; @property (nonatomic, weak) id<CycleScrollViewDelegate> delegate; @end
代理方法動畫
@protocol CycleScrollViewDelegate <NSObject> - (void)cycleScrollView:(CycleScrollView *)cycleScrollView didSelectImageView:(NSInteger)index; @end
#import "CycleScrollView.h" #import "ImageModel.h" //圖片model #import "UIImageView+WebCache.h" //SDWebImage設置網絡圖片 #define c_width (self.bounds.size.width+10) //兩張圖片以前有10點的間隔 #define c_height (self.bounds.size.height) @implementation CycleScrollView { UIPageControl *_pageControl; //分頁控件 NSMutableArray *_curImageArray; //當前顯示的圖片數組 NSInteger _curPage; //當前顯示的圖片位置 NSTimer *_timer; //定時器 }
重寫init
方法atom
- (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { //滾動視圖 self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, c_width, c_height)]; self.scrollView.contentSize = CGSizeMake(c_width*3, 0); self.scrollView.contentOffset = CGPointMake(c_width, 0); self.scrollView.pagingEnabled = YES; self.scrollView.showsHorizontalScrollIndicator = NO; self.scrollView.delegate = self; [self addSubview:self.scrollView]; //分頁控件 _pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, c_height-30, self.bounds.size.width, 30)]; _pageControl.userInteractionEnabled = NO; _pageControl.hidesForSinglePage = YES; _pageControl.currentPageIndicatorTintColor = [UIColor redColor]; _pageControl.pageIndicatorTintColor = [UIColor grayColor]; [self addSubview:_pageControl]; //初始化數據,當前圖片默認位置是0 _curImageArray = [[NSMutableArray alloc] initWithCapacity:0]; _curPage = 0; } return self; }
scrollView
的代理方法url
#pragma mark - UIScrollViewDelegate - (void)scrollViewDidScroll:(UIScrollView *)scrollView { //若是scrollView當前偏移位置x大於等於兩倍scrollView寬度 if (scrollView.contentOffset.x >= c_width*2) { //當前圖片位置+1 _curPage++; //若是當前圖片位置超過數組邊界,則設置爲0 if (_curPage == [self.imageArray count]) { _curPage = 0; } //刷新圖片 [self reloadData]; //設置scrollView偏移位置 [scrollView setContentOffset:CGPointMake(c_width, 0)]; } //若是scrollView當前偏移位置x小於等於0 else if (scrollView.contentOffset.x <= 0) { //當前圖片位置-1 _curPage--; //若是當前圖片位置小於數組邊界,則設置爲數組最後一張圖片下標 if (_curPage == -1) { _curPage = [self.imageArray count]-1; } //刷新圖片 [self reloadData]; //設置scrollView偏移位置 [scrollView setContentOffset:CGPointMake(c_width, 0)]; } } //中止滾動的時候回調 - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { //設置scrollView偏移位置 [scrollView setContentOffset:CGPointMake(c_width, 0) animated:YES]; }
重寫圖片數組的set
方法代理
- (void)setImageArray:(NSMutableArray *)imageArray { _imageArray = imageArray; //設置分頁控件的總頁數 _pageControl.numberOfPages = imageArray.count; //刷新圖片 [self reloadData]; //開啓定時器 if (_timer) { [_timer invalidate]; _timer = nil; } //判斷圖片長度是否大於1,若是一張圖片不開啓定時器 if ([imageArray count] > 1) { _timer = [NSTimer timerWithTimeInterval:5 target:self selector:@selector(timerScrollImage) userInfo:nil repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSDefaultRunLoopMode]; [[NSRunLoop currentRunLoop] runMode:UITrackingRunLoopMode beforeDate:[NSDate date]]; } }
刷新圖片的方法code
- (void)reloadData { //設置頁數 _pageControl.currentPage = _curPage; //根據當前頁取出圖片 [self getDisplayImagesWithCurpage:_curPage]; //從scrollView上移除全部的subview NSArray *subViews = [self.scrollView subviews]; if ([subViews count] > 0) { [subViews makeObjectsPerformSelector:@selector(removeFromSuperview)]; } //建立imageView for (int i = 0; i < 3; i++) { UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(c_width*i, 0, self.bounds.size.width, c_height)]; imageView.userInteractionEnabled = YES; [self.scrollView addSubview:imageView]; //設置網絡圖片 ImageModel *model = _curImageArray[i]; NSURL *url = [NSURL URLWithString:model.image_url]; [imageView sd_setImageWithURL:url placeholderImage:[UIImage imageNamed:@"placeholder_320x120.png"]]; //tap手勢 UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapImage:)]; [imageView addGestureRecognizer:tap]; } }
獲取圖片
- (void)getDisplayImagesWithCurpage:(NSInteger)page { //取出開頭和末尾圖片在圖片數組裏的下標 NSInteger front = page - 1; NSInteger last = page + 1; //若是當前圖片下標是0,則開頭圖片設置爲圖片數組的最後一個元素 if (page == 0) { front = [self.imageArray count]-1; } //若是當前圖片下標是圖片數組最後一個元素,則設置末尾圖片爲圖片數組的第一個元素 if (page == [self.imageArray count]-1) { last = 0; } //若是當前圖片數組不爲空,則移除全部元素 if ([_curImageArray count] > 0) { [_curImageArray removeAllObjects]; } //當前圖片數組添加圖片 [_curImageArray addObject:self.imageArray[front]]; [_curImageArray addObject:self.imageArray[page]]; [_curImageArray addObject:self.imageArray[last]]; }
定時器的方法
- (void)timerScrollImage { //刷新圖片 [self reloadData]; //設置scrollView偏移位置 [self.scrollView setContentOffset:CGPointMake(c_width*2, 0) animated:YES]; }
tap
圖片的方法
- (void)tapImage:(UITapGestureRecognizer *)tap { //設置代理 if ([_delegate respondsToSelector:@selector(cycleScrollView:didSelectImageView:)]) { [_delegate cycleScrollView:self didSelectImageView:_curPage]; } }
dealloc
方法
- (void)dealloc { //代理指向nil,關閉定時器 self.scrollView.delegate = nil; [_timer invalidate]; } @end
viewController裏面的代碼
#import "CycleScrollView.h" @interface RootViewController:BaseViewController<CycleScrollViewDelegate> @property (nonatomic, strong) CycleScrollView *imageScrollView; self.imageScrollView = [[CycleScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 120)]; self.imageScrollView.delegate = self; [headerView addSubview:self.imageScrollView];
獲取到的網絡數據方法裏,設置循環滾動圖片的圖片數組
if ( [[resultDict objectForKey:@"big_image_list"] count] > 0) { self.imageArray = [resultDict objectForKey:@"big_image_list"]; self.imageScrollView.imageArray = self.imageArray; }
代理方法回調
#pragma mark - CycleScrollViewDelegate - (void)cycleScrollView:(CycleScrollView *)cycleScrollView didSelectImageView:(NSInteger)index { NSLog(@"點擊了第%ld張圖片",(long)index+1); ImageModel *model = self.imageArray[index]; }
處理圖片正好滾動了一半app進入到後臺,再次打開的時候是滾動到一半狀態的問題。
- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; //設置圖片循環滾動,若是偏移位置大於330,則設置爲330 if (self.imageScrollView.scrollView.contentOffset.x > 330) { self.imageScrollView.scrollView.contentOffset = CGPointMake(330*2, 0); } }