對於圖像輪播框架的實現,網上有很多種方法,可以使用UIScrollView,也可以使用UICollectionView。
今天就撸一波代碼,打算使用3個UIImageView實現,這樣比較節省內存(個人偏向於這個方案),當然由於UICollectionView的Cell有復用機制,也比較好。
思路:1)在UIScrollView上面添加3個UIImageView,分別為leftImageView,centerImageView,RightImageView

2)UIScrollView初始化時,contentOffset停留在中間的UIImageView
3)使用一個定時器,定時器觸發是,把contentOffset從中間通過動畫滑動到第三個UIImageView的位置
4)滑動完成時候,要進行最關鍵的復位操作,就是迅速把contentOffset切換回第二個UIImageView的位置,但是切換前,先centerImageView.image = rightjImageView.image,注意,這裡不適用動畫,所以用戶看不出來切換了
5)下次定時器觸發時,又把contentOffset從第二個位置通過動畫滑動到第三個位置
6)事實上2個UIImageView就可以實現,但是左邊一直有一個提供用戶手動向左滑動
不費話了,貼代碼:
頭文件:
// // CHRDanTangHeaderScrollView.h // test // // Created by Chen Heren on 16/10/12. // Copyright (c) 2016年 Chen Heren. All rights reserved. // #import@class CHRDanTangHeaderScrollView; @protocol CHRDanTangHeaderScrollViewDelegate -(void)DanTangHeaderScrollView:(CHRDanTangHeaderScrollView *)scrollView selectedAt:(NSInteger)index; @end @interface CHRDanTangHeaderScrollView : UIView @property (strong, nonatomic) NSArray *imageUrls; @property (nonatomic) CGFloat intervalTime; @property (weak, nonatomic) id delegate; -(instancetype)initWithFrame:(CGRect)frame ImageUrls:(NSArray *)imageUrls IntervalTime:(CGFloat)intervalTime; @end
源文件:
//
// CHRDanTangHeaderScrollView.m
// 采用3個UIImageView實現循環顯示
// 思路:暗渡陳倉
// 定時器Fire時,正常進行滑動,待滑動完成,重新把視圖contentoffset恢復到中間uiimageview的狀態
// Created by Chen Heren on 16/10/12.
// Copyright (c) 2016年 Chen Heren. All rights reserved.
//
#import "CHRDanTangHeaderScrollView.h"
#import "UIImageView+WebCache.h"
@interface CHRDanTangHeaderScrollView ()
///滑動視圖
@property (strong, nonatomic) UIScrollView *scrollView;
///指示器
@property (strong, nonatomic) UIPageControl *pageControl;
///左UIImageView
@property (strong, nonatomic) UIImageView *leftImageView;
///中間UIImageView
@property (strong, nonatomic) UIImageView *centerImageView;
///右UIImageView
@property (strong, nonatomic) UIImageView *rightImageView;
@property (nonatomic) NSInteger currentPage;
@property (strong, nonatomic) NSTimer *timer;
@end
@implementation CHRDanTangHeaderScrollView
-(instancetype)initWithFrame:(CGRect)frame ImageUrls:(NSArray *)imageUrls IntervalTime:(CGFloat)intervalTime{
self = [self initWithFrame:frame];
if (self) {
self.imageUrls = [NSArray arrayWithArray:imageUrls];
self.intervalTime = intervalTime;
self.currentPage = 0;
[self setupUI];
}
return self;
}
-(void)setupUI{
[self addSubview:self.scrollView];
[self addSubview:self.pageControl];
[self setupImageView];
[self setupTimer];
}
-(UIScrollView *)scrollView{
if (_scrollView == nil) {
_scrollView = [[UIScrollView alloc]initWithFrame:self.bounds];
_scrollView.contentSize = CGSizeMake(CGRectGetWidth(self.scrollView.frame) * 3, CGRectGetHeight(self.scrollView.frame));
_scrollView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
_scrollView.delegate = self;
_scrollView.pagingEnabled = YES;
_scrollView.showsHorizontalScrollIndicator = NO;
_scrollView.decelerationRate = 1.0;
_scrollView.contentOffset = CGPointMake(CGRectGetWidth(self.scrollView.frame), 0);
}
return _scrollView;
}
-(UIPageControl *)pageControl{
if (_pageControl == nil) {
_pageControl = [[UIPageControl alloc]initWithFrame:CGRectMake(self.frame.size.width/2-50, self.frame.size.height-35, 100, 30)];
_pageControl.numberOfPages = self.imageUrls.count;
_pageControl.currentPageIndicatorTintColor = [UIColor whiteColor];
_pageControl.pageIndicatorTintColor = [UIColor lightGrayColor];
}
return _pageControl;
}
-(void)setupImageView{
self.leftImageView = [[UIImageView alloc]initWithFrame:CGRectMake(self.frame.size.width *0, 0, self.frame.size.width, self.frame.size.height)];
self.centerImageView = [[UIImageView alloc]initWithFrame:CGRectMake(self.frame.size.width *1, 0, self.frame.size.width, self.frame.size.height)];
self.rightImageView = [[UIImageView alloc]initWithFrame:CGRectMake(self.frame.size.width *2, 0, self.frame.size.width, self.frame.size.height)];
[self.leftImageView sd_setImageWithURL:[self getImageUrlBeforeIndex:self.currentPage]];
[self.centerImageView sd_setImageWithURL:[self getImageUrlAtIndex:self.currentPage]];
[self.rightImageView sd_setImageWithURL:[self getImageUrlAfterIndex:self.currentPage]];
self.leftImageView.contentMode = UIViewContentModeScaleAspectFit;
self.centerImageView.contentMode = UIViewContentModeScaleAspectFit;
self.rightImageView.contentMode = UIViewContentModeScaleAspectFit;
///用戶看到的只有中間視圖,所以為了簡單起見,只需要添加中間視圖的點擊響應
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(imageViewTap)];
self.centerImageView.userInteractionEnabled = YES;
[self.centerImageView addGestureRecognizer:tap];
[self.scrollView addSubview:self.leftImageView];
[self.scrollView addSubview:self.centerImageView];
[self.scrollView addSubview:self.rightImageView];
}
-(void)setupTimer{
self.timer = [NSTimer timerWithTimeInterval:self.intervalTime target:self selector:@selector(timerTick) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop]addTimer:_timer forMode:NSRunLoopCommonModes];
}
-(void)timerTick{
self.currentPage++;
if (self.currentPage == self.imageUrls.count) {
self.currentPage = 0;
}
///此處設置動畫的時間一定要小於滑動的時間
[UIView animateWithDuration:1 animations:^{
///動畫發生的滑動
self.centerImageView.userInteractionEnabled =NO;
self.scrollView.contentOffset =CGPointMake(CGRectGetWidth(self.scrollView.frame) * 2, 0);
} completion:^(BOOL finished) {
///滑動完成後,把當前現實的imageview重現移動回中間位置,此處不能使用動畫,用戶感覺不到
///移動前,先把中間imageview的image設置成當前現實的iamge
self.centerImageView.userInteractionEnabled = YES;
self.leftImageView.image = self.centerImageView.image;
self.centerImageView.image = self.rightImageView.image;
self.scrollView.contentOffset =CGPointMake(CGRectGetWidth(self.scrollView.frame) * 1, 0);
[self.rightImageView sd_setImageWithURL:[self getImageUrlAfterIndex:self.currentPage]];
self.pageControl.currentPage = self.currentPage;
}];
}
#pragma mark - 用戶點擊
-(void)imageViewTap{
NSLog(@"tap at :%ld",self.currentPage);
[self.delegate DanTangHeaderScrollView:self selectedAt:self.currentPage];
}
#pragma mark - 循環獲取URL
-(NSURL *)getImageUrlBeforeIndex:(NSInteger)index{
if (index == 0) {
return [self.imageUrls lastObject];
}else{
return self.imageUrls[index-1];
}
}
-(NSURL *)getImageUrlAfterIndex:(NSInteger)index{
if (index == (self.imageUrls.count - 1)) {
return [self.imageUrls firstObject];
}else{
return self.imageUrls[index+1];
}
}
-(NSURL *)getImageUrlAtIndex:(NSInteger)index{
if (index<0 || index >= self.imageUrls.count) {
return nil;
}else{
return self.imageUrls[index];
}
}
#pragma mark - scrollView滑動事件
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
///有用戶手動拖動,則停止定時器
[self.timer invalidate];
}
-(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
///用戶滑動停止,重新啟動定時器
[self setupTimer];
}
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
NSInteger index = scrollView.contentOffset.x/scrollView.frame.size.width;
if (index ==0) {
//向左滑動
self.currentPage--;
if (self.currentPage <0 ) {
self.currentPage = self.imageUrls.count;
}
self.rightImageView.image = self.centerImageView.image;
self.centerImageView.image = self.leftImageView.image;
scrollView.contentOffset = CGPointMake(CGRectGetWidth(self.scrollView.frame) * 1, 0);
[self.leftImageView sd_setImageWithURL:[self getImageUrlBeforeIndex:self.currentPage]];
self.pageControl.currentPage = self.currentPage;
}else if(index == 2){
///向右滑動
self.currentPage++;
if (self.currentPage ==self.imageUrls.count ) {
self.currentPage = 0;
}
self.leftImageView.image = self.centerImageView.image;
self.centerImageView.image = self.rightImageView.image;
scrollView.contentOffset = CGPointMake(CGRectGetWidth(self.scrollView.frame) * 1, 0);
[self.rightImageView sd_setImageWithURL:[self getImageUrlAfterIndex:self.currentPage]];
self.pageControl.currentPage = self.currentPage;
}
///沒有滑動一頁
}
@end
#import "ViewController.h" #import "CHRDanTangHeaderScrollView.h" @interface ViewController ()@end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. NSURL *url = [[NSBundle mainBundle]URLForResource:@"1" withExtension:@".png"]; NSURL *ur2 = [[NSBundle mainBundle]URLForResource:@"2" withExtension:@".png"]; NSURL *ur3 = [[NSBundle mainBundle]URLForResource:@"3" withExtension:@".png"]; NSURL *ur4 = [[NSBundle mainBundle]URLForResource:@"4" withExtension:@".png"]; CHRDanTangHeaderScrollView *scrollView = [[CHRDanTangHeaderScrollView alloc]initWithFrame:CGRectMake(0, 100, self.view.frame.size.width, 200) ImageUrls:@[url,ur2,ur3,ur4] IntervalTime:2]; scrollView.delegate = self; [self.view addSubview:scrollView]; } -(void)DanTangHeaderScrollView:(CHRDanTangHeaderScrollView *)scrollView selectedAt:(NSInteger)index{ NSLog(@"%ld",index); } @end


demo傳送門:https://git.oschina.net/heren/CHRScrollView.git