UIScrollView循環滾動圖片

轉載自  http://www.jianshu.com/p/aa73c273baf2數組

咱們會常常用到循環滾動圖片,包括定時滾動,點擊觸發事件。
之前所知道的循環滾動圖片的方法是這樣的。好比:一共5張圖片,位置爲1,2,3,4,5。網絡

  1. 建立7個imageView
  2. 將最後一張圖片放到第一張圖片前面,將第一張圖片放到最後一張後面,位置爲5,1,2,3,4,5,1。
  3. 最後一張圖片滾動到第一張圖片時,先從第二個圖片5滾動到第二個圖片1,滾動完以後把位置設置爲第一個圖片1。從後向前滾動一樣的原理。
  4. scrollViewDidScroll的代理方法裏面判斷scrollView.contentOffset.x>320*6-1,將scrollView的偏移量設置爲320的位置,動畫設置爲NO
  5. 這樣作的緣由是從第二個圖片5滾動到第二個圖片1以後偏移量是320*6,這個值是大於320*6-1的,進入到if語句,將scrollView設置320的位置,則就是第一個圖片1的位置,這樣就形成一個視覺差,是從最後一張圖片滾動到第一張圖片的。

之前是那麼用的,可是後來以爲這樣比較佔資源,也比較麻煩,如今是這樣的,無論多少張圖片只建立3個imageViewapp

  1. viewController中取到圖片數據源,建立當前須要展現的圖片數組長度是3,當前展現的圖片位置默認是0。
  2. 當前數組根據當前位置取出3張圖片,當前展現的圖片的前一張和後一張。若是當前須要展現的圖片是第一張,則當前數組中的3張圖片爲圖片五、圖片一、圖片2。若是當前須要展現的圖片是最後一張圖片,則當前數組中的3張圖片爲圖片四、圖片五、圖片1。
  3. 這樣展現的圖片是第2張圖片,偏移量爲320,滑動到下一張圖片的時候,設置當前位置爲1,設置當前數組圖片爲圖片一、圖片二、圖片3,刷新UI,而且把scrollView的偏移量設置爲320,即展現的圖片永遠在中間。
  4. 點擊圖片觸發的事件經過代理傳出當前的圖片位置。

CycleScrollView.h中的代碼

#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

CycleScrollView.m中的代碼

#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);
    }
}
相關文章
相關標籤/搜索