IOS无限轮播图

思路:在ScrollView的contentSiz设置成ScrollView宽的度的三倍。创建三个循环的View。当滑动的时候,正常滑动活动结束。滑动结束设置contentOffset将视图滑动到中间去。将后面的数据赋值到中间。。。简单说就是视图只显示中间一张视,交换数据实现不同数据的显示。。

#import <UIKit/UIKit.h>



@protocol YQImageLoopDelegate <NSObject>



- (void)YQImageLoopConfigDataArray:(NSArray *)yq_dataArray loopView:(UIView *)yq_loopView index:(NSInteger)index;

@optional

- (void)YQImageLoopClickImageOfindex:(NSInteger)index dataArray:(NSArray *)yq_dataArray;



@end







@interface YQImageLoop : UIView



- (instancetype)initWithFrame:(CGRect)frame loopView:(UIView *)loopView loopDelagate:(id<YQImageLoopDelegate>)delegate;// 初始化

@property (nonatomic, strong) UIScrollView *yq_scrollView;

@property (nonatomic, strong) UIPageControl *yq_pageControl;

@property (nonatomic, assign) NSTimeInterval yq_timerLoopTime;     // timer循环时间

@property (nonatomic, assign) NSTimeInterval yq_animactionTime;    // 动画时间

@property (nonatomic, strong) NSArray *yq_dataArray;        // 循环的数据

@property (nonatomic, assign) BOOL yq_isLoop;                      // 是否循环

@property (nonatomic, assign) id<YQImageLoopDelegate>delegate;     // 代理



#pragma mark 事件-timer事件

-(void)addTimer:(NSTimeInterval)timeInterval;

- (void)cancelTimerLoop;

@end

 

#import "YQImageLoop.h"



typedef NS_ENUM(NSInteger, YQScrollDirection)

{

    YQRight,

    YQLeft,

};



@interface YQImageLoop ()<UIScrollViewDelegate>

@property (nonatomic, strong) NSTimer *yq_timer;            // 循环timer定时器

@property (nonatomic, strong) UIView *yq_loopView;          // 循环的视图

@property (nonatomic, strong) NSMutableArray *yq_recordLoopViewArray; // 存储循环视图

@property (nonatomic, assign) BOOL isDragg;    // 是否拖拽

@property (nonatomic, assign) BOOL isGetData;  // 是否活的轮播的数据



@property (nonatomic, strong) UITapGestureRecognizer *tapGR;



@end



@implementation YQImageLoop





- (instancetype)initWithFrame:(CGRect)frame loopView:(UIView *)loopView loopDelagate:(id<YQImageLoopDelegate>)delegate

{

    self = [super initWithFrame:frame];

    if (self) {

        _delegate = delegate;

        _yq_loopView = loopView;

        [self addDatas];

        [self addViews];

    }

    return self;

}



#pragma mark 初始

- (void)addViews

{

    self.yq_scrollView.frame = self.frame;

    [self addSubview:self.yq_scrollView];

    [self addSubview:self.yq_pageControl];

    

    self.tapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGRAction:)];

    [self addGestureRecognizer:_tapGR];

}

- (void)addDatas

{

    _isGetData = NO;

     _isDragg = NO;

    _yq_dataArray = [[NSMutableArray alloc] initWithCapacity:30];

     [self addObserver:self forKeyPath:@"yq_dataArray" options:NSKeyValueObservingOptionNew context:nil];

}

#pragma mark 初始-事件

#pragma mark 初始-事件-添加循环视图

- (void)configScrollViewLoopView

{

    for (int i=0; i<3; i++) {

         UIView *newLoopView = [self duplicate:self.yq_loopView];

        newLoopView.frame = CGRectMake(self.frame.size.width*i, 0, self.frame.size.width, self.frame.size.height);

        [self.yq_recordLoopViewArray addObject:newLoopView];

        [_yq_scrollView addSubview:newLoopView];

    }

}

// 复制一份view

- (UIView*)duplicate:(UIView*)view1

{

    NSData * tempArchive = [NSKeyedArchiver archivedDataWithRootObject:view1];

    return [NSKeyedUnarchiver unarchiveObjectWithData:tempArchive];

}



- (void)setYq_timerLoopTime:(NSTimeInterval)yq_timerLoopTime

{

    _yq_timerLoopTime = yq_timerLoopTime;

    [self addTimer:_yq_timerLoopTime];

}



#pragma mark 代理-delegate

#pragma mark 代理-scrollViewDelegate



- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView

{

    // 拖拽开始

    self.isDragg = YES;

    [self cancelTimerLoop];

    

}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView

{

    // 拖拽完成

    if (self.isDragg == YES) {

        [self addTimer:self.yq_timerLoopTime];

        self.isDragg = NO;

    }

    // changDataOrPage

    [self YQScrollViewDidEndDecelerating:_yq_scrollView.contentOffset.x isGetData:_isGetData];

}





#pragma mark 事件

#pragma mark 事件-timer事件

-(void)addTimer:(NSTimeInterval)timeInterval

{

    if (self.yq_timer == nil) {

        self.yq_timer = [NSTimer scheduledTimerWithTimeInterval:timeInterval target:self selector:@selector(timeLoopAction:) userInfo:nil repeats:YES];

        [[NSRunLoop currentRunLoop] addTimer:_yq_timer forMode:NSRunLoopCommonModes];

    }

}

- (void)cancelTimerLoop

{

    [self.yq_timer invalidate];

    self.yq_timer = nil;

}

- (void)timeLoopAction:(NSTimer *)sender

{

    [UIView animateWithDuration:self.yq_animactionTime animations:^{

        self.yq_scrollView.contentOffset = CGPointMake(self.frame.size.width*2, 0);

    } completion:^(BOOL finished) {

        self.yq_scrollView.contentOffset = CGPointMake(self.frame.size.width, 0);

        if (_isGetData == YES) {

            [self changeDataAndPage:YQLeft];

        }else{

            [self changePage:YQLeft];

        }

    }];

}



#pragma mark 事件-滑动完成改变数据、

- (void)YQScrollViewDidEndDecelerating:(CGFloat)contentOffsetX isGetData:(BOOL)getData

{

        if (contentOffsetX == 0) {

            if (getData == YES){

                [self changeDataAndPage:YQRight];

            }else{

                [self changePage:YQRight];

            }

            _yq_scrollView.contentOffset = CGPointMake(self.frame.size.width, 0);

        }else if(contentOffsetX == self.frame.size.width*2){

            if (getData == YES) {

                [self changeDataAndPage:YQLeft];

            }else{

                [self changePage:YQLeft];

            }

            _yq_scrollView.contentOffset = CGPointMake(self.frame.size.width, 0);

        }

}





// data and page

- (void)changeDataAndPage:(YQScrollDirection)scrollDirection

{

    [self changePage:scrollDirection];

    [self changeData];

}

// page

- (void)changePage:(YQScrollDirection)scrollDirection

{

    if (scrollDirection == YQRight) {

        // pageCotrol 变化

        if (_yq_pageControl.currentPage == 0){

            _yq_pageControl.currentPage = _yq_pageControl.numberOfPages-1;

        }else{

            _yq_pageControl.currentPage -= 1;

        }

    }else if(scrollDirection == YQLeft){

        if(_yq_pageControl.currentPage == _yq_pageControl.numberOfPages-1){

            _yq_pageControl.currentPage = 0;

        }else{

            _yq_pageControl.currentPage += 1;

        }

    }

}

// data

- (void)changeData

{

    if (_yq_pageControl.currentPage == 0){

        if (_delegate && [_delegate respondsToSelector:@selector(YQImageLoopConfigDataArray:loopView:index:)]) {

            [_delegate YQImageLoopConfigDataArray:_yq_dataArray loopView:_yq_recordLoopViewArray[0] index:_yq_pageControl.numberOfPages-1];

            [_delegate YQImageLoopConfigDataArray:_yq_dataArray loopView:_yq_recordLoopViewArray[1] index:0];

            [_delegate YQImageLoopConfigDataArray:_yq_dataArray loopView:_yq_recordLoopViewArray[2] index:1];

        }

    }else if(_yq_pageControl.currentPage == _yq_pageControl.numberOfPages-1){

        if (_delegate && [_delegate respondsToSelector:@selector(YQImageLoopConfigDataArray:loopView:index:)]) {

            [_delegate YQImageLoopConfigDataArray:_yq_dataArray loopView:_yq_recordLoopViewArray[0] index:_yq_pageControl.currentPage-1];

            [_delegate YQImageLoopConfigDataArray:_yq_dataArray loopView:_yq_recordLoopViewArray[1] index:_yq_pageControl.currentPage];

            [_delegate YQImageLoopConfigDataArray:_yq_dataArray loopView:_yq_recordLoopViewArray[2] index:0];

        }

    }else{

        if (_delegate && [_delegate respondsToSelector:@selector(YQImageLoopConfigDataArray:loopView:index:)]) {

            [_delegate YQImageLoopConfigDataArray:_yq_dataArray loopView:_yq_recordLoopViewArray[0] index:_yq_pageControl.currentPage-1];

            [_delegate YQImageLoopConfigDataArray:_yq_dataArray loopView:_yq_recordLoopViewArray[1] index:_yq_pageControl.currentPage];

            [_delegate YQImageLoopConfigDataArray:_yq_dataArray loopView:_yq_recordLoopViewArray[2] index:_yq_pageControl.currentPage+1];

        }

    }

}



#pragma mark 监听

#pragma mark 监听-属性

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context

{

    if ([keyPath isEqualToString:@"yq_dataArray"]) {

        if (change[@"new"] != nil && ([change[@"new"] isKindOfClass:[NSArray class]] && ([(NSArray *)change[@"new"] count] != 0) && ([change[@"new"] isKindOfClass:[NSDictionary class]]|| [(NSDictionary *)change[@"new"] count] != 0))){

            _isGetData = YES;

            [self observeValueFinish];

        }

    }

}

#pragma mark 监听-事件

- (void)observeValueFinish

{

    self.yq_pageControl.numberOfPages = self.yq_dataArray.count;

    if (_delegate && [_delegate respondsToSelector:@selector(YQImageLoopConfigDataArray:loopView:index:)]) {

        [_delegate YQImageLoopConfigDataArray:_yq_dataArray loopView:_yq_recordLoopViewArray[0] index:_yq_dataArray.count-1];

        [_delegate YQImageLoopConfigDataArray:_yq_dataArray loopView:_yq_recordLoopViewArray[1] index:0];

        [_delegate YQImageLoopConfigDataArray:_yq_dataArray loopView:_yq_recordLoopViewArray[2] index:1];

    }

}





#pragma mark 点击事件

- (void)tapGRAction:(UITapGestureRecognizer *)sender

{

    if (_delegate && [_delegate respondsToSelector:@selector(YQImageLoopClickImageOfindex:dataArray:)]) {

        [_delegate YQImageLoopClickImageOfindex:self.yq_pageControl.currentPage dataArray:_yq_dataArray];

    }

}





#pragma mark setter and getter

- (UIPageControl *)yq_pageControl

{

    if (_yq_pageControl == nil) {

        _yq_pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, self.frame.size.height-30, self.frame.size.width, 30)];

        _yq_pageControl.numberOfPages = 4;

    }

    return _yq_pageControl;

}

- (UIScrollView *)yq_scrollView

{

    if (_yq_scrollView == nil){

        _yq_scrollView = [[UIScrollView alloc] initWithFrame:self.frame];

        _yq_scrollView.delegate = self;

        _yq_scrollView.contentSize = CGSizeMake(CGRectGetWidth(self.frame)*3, CGRectGetHeight(self.frame));

        _yq_scrollView.contentOffset = CGPointMake(CGRectGetWidth(self.frame), 0);

        _yq_scrollView.pagingEnabled = YES;

        _yq_scrollView.bounces = NO;

        _yq_scrollView.showsHorizontalScrollIndicator = NO;

        _yq_scrollView.showsVerticalScrollIndicator = NO;

        [self configScrollViewLoopView];

    }

    return _yq_scrollView;

}



- (NSMutableArray *)yq_recordLoopViewArray

{

    if (_yq_recordLoopViewArray == nil) {

        _yq_recordLoopViewArray = [[NSMutableArray alloc] initWithCapacity:30];

    }

    return _yq_recordLoopViewArray;

}





- (void)dealloc

{

    [self removeObserver:self forKeyPath:@"yq_dataArray" context:nil];

}

 

注意事项:NSTimer 加到当前的runloop中,才能真正的实现循环。。。大家不良了解runloop的可以自行百度去吧。在下就不在这班门弄斧,讲一些与主题无关的了。。。

看一下如何使用吧

// 图片资源

     self.imageAddressArray = [[NSArray alloc] initWithObjects:@"http://img1.3lian.com/2015/w1/47/d/1.jpg",@"http://img1.3lian.com/2015/w1/47/d/9.jpg",@"http://img1.3lian.com/2015/w1/47/d/8.jpg",@"http://img1.3lian.com/2015/w2/10/d/46.jpg",@"http://img1.3lian.com/2015/w1/47/d/7.jpg",@"http://img1.3lian.com/2015/w1/47/d/6.jpg", nil];

    

    // 自定义循环视图

    UIImageView *image = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"zw.png"]];

    //_________________________________________________________

    _yqImageLoop = [[YQImageLoop alloc] initWithFrame:self.view.frame loopView:image loopDelagate:self];

    _yqImageLoop.yq_pageControl.currentPageIndicatorTintColor = [UIColor redColor];

    _yqImageLoop.yq_timerLoopTime = 3.0f;

    _yqImageLoop.yq_animactionTime = 1.5f;

    [self.view addSubview:_yqImageLoop];

    

    

    // 延迟赋数据,模仿网络请求

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

        _yqImageLoop.yq_dataArray = _imageAddressArray;

    });

 

// 轮播图赋值数据

- (void)YQImageLoopConfigDataArray:(NSArray *)yq_dataArray loopView:(UIView *)yq_loopView index:(NSInteger)index

{

    [((UIImageView *)yq_loopView) sd_setImageWithURL:[NSURL URLWithString:yq_dataArray[index]] placeholderImage:[UIImage imageNamed:@"zw.png"]];

}



// 点击轮播

- (void)YQImageLoopClickImageOfindex:(NSInteger)index dataArray:(NSArray *)yq_dataArray

{

    NSLog(@"%@",yq_dataArray[index]);

}



/*

  在视图将要出现的时候加上事件循环, 消失的时候取消事件循环

 */

- (void)viewWillAppear:(BOOL)animated

{

    [super viewWillAppear:animated];

    [_yqImageLoop addTimer:3.0f]; // 添加时间循环

}



- (void)viewDidDisappear:(BOOL)animated

{

    [super viewDidDisappear:animated];

    [_yqImageLoop cancelTimerLoop]; // 取消事件循环

}

 

有什么好的建议,有更好的想法。联系826001000.谢谢 

 

你可能感兴趣的:(ios)