码迷,mamicode.com
首页 > 其他好文 > 详细

无限轮播图

时间:2015-05-30 21:03:52      阅读:111      评论:0      收藏:0      [点我收藏+]

标签:

思路:在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]; // 取消事件循环
}

 

无限轮播图

标签:

原文地址:http://www.cnblogs.com/IT-xiao-jian/p/4540904.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!