iOS开发之只用一个方法实现图片的轮播

##摘要
本文详细的讲述了如何封装一个只用一个方法就实现自动循环轮播的广告视图,依赖于SDWebImage。

###效果图

FGGAutomaticScrollView简介:


初始化方法,两种:

1.从网络加载图片:

1
2
3
[[FGGAutoScrollView alloc] initWithFrame:(CGRect)frame
imageURLs:(NSArray *)URLArray
imageDidSelectedBlock:(FGGImageClickBlock) didSelectedImageAtIndex];

2.从本地加载图片:

1
2
3
[[FGGAutoScrollView alloc] initWithFrame:(CGRect)frame
localImageNames:(NSArray *)imageNames
imageDidSelectedBlock:(FGGImageClickBlock) didSelectedImageAtIndex;

提示:

若不需要为图片添加点击事件,初始化时,点击图片的回调block置为nil就可以了。

###使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
NSArray *array = @[@"http://i.okaybuy.cn/images/multipic/new/201506/fe/fe6b322427edad3dd6c7916116a9a15b.jpg,
"@"http://i.okaybuy.cn/images/multipic/new/201505/88/888d8cf6a769c401af2ced0140fa90f3.jpg",
@"http://i.okaybuy.cn/images/multipic/new/201506/53/532a6028830f9d7e39b5bce9e5e60e52.jpg"];

_bannerView=[[FGGAutoScrollView alloc]initWithFrame:CGRectMake(20, 100, self.view.frame.size.width-40, 200) placeHolderImage:nil imageURLs:array imageDidSelectedBlock:^(NSInteger selectedIndex) {
switch (selectedIndex) {
case 0:
NSLog(@"你选择了第%ld张图片",selectedIndex);
break;
case 1:
NSLog(@"你选择了第%ld张图片",selectedIndex);
break;
case 2:
NSLog(@"你选择了第%ld张图片",selectedIndex);
break;
default:
break;
}
}];
[self.view addSubview:_bannerView];

若你想添加自动滚动的回调事件(可不设置):

1
2
3
4
_bannerView.imageDidScrolledBlock=^(NSInteger index){
NSLog(@"滚动到了第%ld张",index);
};
[self.view addSubview:_bannerView];

若你的图片是从链接是从网上获取的,你可以在获取图片的数组imgsArray后,调用set方法即可替换数据源,并且会自动reload视图:

1
_bannerView.imageURLArray=imgsArray;

##实现细节
搞一个自定义的视图`FGGAutoScrollView

1
@interface FGGAutoScrollView : UIView<UIScrollViewDelegate>

设置如下属性:

1
2
3
4
5
6
7
8
9
10
11
/**点击照片的回调*/
@property(nonatomic,copy,readonly)FGGImageClickBlock didSelectedImageAtIndex;

@property(nonatomic,copy) FGGImageScrolledBlock imageDidScrolledBlock;

/**
* 图片的urlString链接数组
*
* 可以通过调用其set方法,来重载数据源和视图
*/
@property(nonatomic,strong)NSArray *imageURLArray;

滚动时间间隔:

1
2
3
4
/**
* 滚动时间间隔 可以自己修改
*/
static double kFGGScrollInterval = 3.0f;

加载网络图片:

1
2
3
4
5
6
7
8
9
10
/**
* 加载网络图片滚动
*
* @param frame frame
* @param URLArray 包含图片URL字符串的数组
* @param didSelectedImageAtIndex 点击图片时回调的block
*
* @return FGGAutoScrollView对象
*/
-(instancetype)initWithFrame:(CGRect)frame placeHolderImage:(UIImage *)placeHolderImage imageURLs:(NSArray *)URLArray imageDidSelectedBlock:(FGGImageClickBlock) didSelectedImageAtIndex;

加载本地图片:

1
2
3
4
5
6
7
8
9
10
/**
* 加载本地图片滚动
*
* @param frame frame
* @param imageNames 本地图片名字数组
* @param didSelectedImageAtIndex 点击图片时回调的block
*
* @return FGGAutoScrollView对象
*/
-(instancetype)initWithFrame:(CGRect)frame placeHolderImage:(UIImage *)placeHolderImage localImageNames:(NSArray *)imageNames imageDidSelectedBlock:(FGGImageClickBlock) didSelectedImageAtIndex;

##实现 FGGAutoScrollView.m

在拓展中添加一个属性:

1
2
3
4
5
6
7
@interface FGGAutoScrollView()
/**
* 滚动视图对象(只读)
*/
@property(nonatomic,strong,readonly)UIScrollView *scroll;

@end

添加计数器,默认图片等成员变量

1
2
3
4
5
6
7
8
9
@implementation FGGAutoScrollView{

//定时器
NSTimer *_timer;
//页码控制器
UIPageControl *_pageControl;
/**默认图片*/
UIImage *_placeHolderImage;
}

加载网络图片:

1
2
3
4
5
6
7
8
9
10
11
12
//加载网络图片的方法
-(instancetype)initWithFrame:(CGRect)frame placeHolderImage:(UIImage *)placeHolderImage imageURLs:(NSArray *)URLArray imageDidSelectedBlock:(FGGImageClickBlock)didSelectedImageAtIndex{

if(self=[super initWithFrame:frame]){

_placeHolderImage=placeHolderImage;
_imageURLArray=URLArray;
_didSelectedImageAtIndex=didSelectedImageAtIndex;
[self createScrollView];
}
return self;
}

加载本地图片:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//加载本地的图片的方法
-(instancetype)initWithFrame:(CGRect)frame placeHolderImage:(UIImage *)placeHolderImage localImageNames:(NSArray *)imageNames imageDidSelectedBlock:(FGGImageClickBlock)didSelectedImageAtIndex{

if(self=[super initWithFrame:frame]){

if(imageNames.count>0){

_placeHolderImage=placeHolderImage;
NSMutableArray *fullPathArray=[NSMutableArray array];
for(int i=0;i<imageNames.count;i++){

NSString *path;
NSString *name=imageNames[i];
if([name hasSuffix:@"jpg"][name hasSuffix:@"png"])
path=[[NSBundle mainBundle] pathForResource:name ofType:nil];
else
path=[[NSBundle mainBundle] pathForResource:name ofType:@"png"];
NSString *fullPath=[NSString stringWithFormat:@"file://%@",[path stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
[fullPathArray addObject:fullPath];
}
_imageURLArray=fullPathArray;
_didSelectedImageAtIndex=didSelectedImageAtIndex;
[self createScrollView];
}
}
return self;
}

创建滚动视图,添加点击手势:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
//构建循环滚动视图
-(void)createScrollView{

if(_scroll){

for(UIView *sub in _scroll.subviews)
[sub removeFromSuperview];
[_scroll removeFromSuperview];
_scroll=nil;
}
_scroll=[[UIScrollView alloc]initWithFrame:self.bounds];
[self addSubview:_scroll];
_scroll.delegate=self;
_scroll.contentSize=CGSizeMake((_imageURLArray.count+1)*self.bounds.size.width, self.bounds.size.height);

_scroll.pagingEnabled=YES;
_scroll.showsHorizontalScrollIndicator=NO;
if(_timer){

[_timer invalidate];
_timer=nil;
}
_timer=[NSTimer scheduledTimerWithTimeInterval:kFGGScrollInterval
target:self
selector:@selector(automaticScroll)
userInfo:nil
repeats:YES];
for(int i=0;i<=_imageURLArray.count;i++){

CGFloat xpos=i*self.bounds.size.width;
UIImageView *imv=[[UIImageView alloc]initWithFrame:CGRectMake(xpos, 0, self.bounds.size.width, self.bounds.size.height)];
//设置灰色底
imv.image=_placeHolderImage;
imv.userInteractionEnabled=YES;

//添加点击图片的手势
UITapGestureRecognizer *tap=[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapImage)];
[imv addGestureRecognizer:tap];
[_scroll addSubview:imv];
NSString *urlString;
if(i<_imageURLArray.count)
urlString=_imageURLArray[i];
else
urlString=_imageURLArray[0];
NSURL *url=[NSURL URLWithString:urlString];
[imv sd_setImageWithURL:url placeholderImage:_placeHolderImage];
}
if(_pageControl)
_pageControl=nil;
_pageControl=[[UIPageControl alloc]init];
_pageControl.center=CGPointMake(self.bounds.size.width/2, self.bounds.size.height-10);
_pageControl.numberOfPages=_imageURLArray.count;
_pageControl.currentPage=0;
_pageControl.pageIndicatorTintColor=[UIColor whiteColor];
_pageControl.currentPageIndicatorTintColor=[UIColor orangeColor];
[self addSubview:_pageControl];
}

自动滚动的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 自动循环滚动
*/
-(void)automaticScroll{

if(_imageURLArray.count>0){

NSInteger index=_scroll.contentOffset.x/self.bounds.size.width;
index++;
if(index==_imageURLArray.count)
index=0;
if(self.imageDidScrolledBlock)
self.imageDidScrolledBlock(index);
_pageControl.currentPage=index;
__weak typeof(self) weakSelf=self;
//添加滚动动画
[UIView animateWithDuration:0.2 animations:^{
weakSelf.scroll.contentOffset=CGPointMake(index*self.bounds.size.width, 0);
}];
}
}

点击图片的回调:

1
2
3
4
5
6
7
8
//点击图片时回调代码块
-(void)tapImage{

if(self.didSelectedImageAtIndex){

self.didSelectedImageAtIndex(_pageControl.currentPage);
}
}

重写数据源的set方法,以重载视图:

1
2
3
4
5
6
7
8
9
10
/**图片数组的setter方法*/
-(void)setImageURLArray:(NSArray *)imageURLArray{

if(![imageURLArray isKindOfClass:[NSArray class]])
return;
_imageURLArray=imageURLArray;
if(_imageURLArray.count==0)
return;
[self createScrollView];
}

滚动的代理方法,若设置了滚动的回调,则在这个方法里回调imageDidScrolledBlock

1
2
3
4
5
6
7
8
9
10
11
#pragma mark - UIScrollView
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{

NSInteger index=_scroll.contentOffset.x/self.bounds.size.width;
if(index==_imageURLArray.count)
index=0;
if(self.imageDidScrolledBlock)
self.imageDidScrolledBlock(index);
_pageControl.currentPage=index;
_scroll.contentOffset=CGPointMake(self.bounds.size.width*index, 0);
}

最后在delloc中销毁计时器

1
2
3
4
5
6
7
8
9
//销毁
-(void)dealloc{

if(_timer){

[_timer invalidate];
_timer=nil;
}
}

最后附上我的GitHub代码地址:FGGAutomaticScrollView,欢迎pull request和star ~
以及我的个人博客:CGPointZero欢迎访问~