思路:在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.谢谢