思路:在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的能夠自行百度去吧。在下就不在這班門弄斧,講一些與主題無關的了。。。app
看一下如何使用吧oop
// 圖片資源 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.謝謝 動畫