今天项目中用到了轮播的功能,原本想着去网上找个第三方的,后来想一下本身实现一个也是挺简单的.因而就有了这篇文章git
总结了一下,一个广告轮播必须含有如下几个功能;github
肯定好要实现的功能,又到了咱们最开心的编码环节.bash
原本我第一时间想到的是利用UiScrollview或者UiCollectionView等组件来实现,不过在之前一篇仿今日头条新闻分页中文章中我讲过一下他们和UIPageViewController的区别.因此今天我就选定UIPageViewController来当咱们此次的主角啦!框架
咱们新建一个BannerView的自定义view,全部的逻辑代码就写里面啦.测试
@property (nonatomic,strong)UIPageViewController *pageCon;
/**
指示器
*/
@property (nonatomic,strong)UIPageControl *indicator;
/**
存放全部的图片地址
*/
@property (nonatomic,strong)NSArray *imageArr;
/**
存放全部的页面
*/
@property (nonatomic,strong)NSMutableArray *controlls;
/**
当前tag值
*/
@property (nonatomic,assign)NSInteger tagIndex;
/**
轮播定时器
*/
@property (nonatomic,strong)NSTimer *timeZ;
/**
回调点击的图片所在的tag值
*/
@property (nonatomic,strong)bannerResult block;
/**
是否在自动轮播
*/
@property (nonatomic,assign)BOOL isAuto;
复制代码
-(instancetype)initWithFrame:(CGRect)frame{
self=[super initWithFrame:frame];
if(self){
[self initView];
}
return self;
}
-(void)initView{
_controlls=[[NSMutableArray alloc]init];
_tagIndex=0;//默认tag==0
_pageCon=[[UIPageViewController alloc]initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
_pageCon.delegate = self;
_pageCon.dataSource = self;
_pageCon.view.frame=self.bounds;
[self addSubview:_pageCon.view];
_indicator=[[UIPageControl alloc]init];
[self addSubview:_indicator];
//这里用了Masonry框架代码,就是底部居中的意思,不想用该框架的能够用其余的约束
[_indicator mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self);
make.bottom.equalTo(self.mas_bottom).offset(10);
}];
}
复制代码
主要是建立轮播页以及轮播页面里面要添加的内容(这里咱们只要放一个图片便可)ui
-(void)initData:(NSArray *)arr block:(bannerResult)block{
_isAuto=false;
_block=block;
_imageArr=arr;
_indicator.numberOfPages=_imageArr.count;
[_imageArr enumerateObjectsUsingBlock:^(NSString* obj, NSUInteger idx, BOOL * _Nonnull stop) {
//建立轮播页
UIViewController *con=[[UIViewController alloc]init];
con.view.frame=self.bounds;
UIImageView *image=[[UIImageView alloc]initWithFrame:self.bounds];
image.contentMode=UIViewContentModeScaleAspectFill;
[image sd_setImageWithURL:[NSURL URLWithString:obj]];
[con.view addSubview:image];
[_controlls addObject:con];
[self setListener:con.view index:idx]; //这是设置每一个页面点击事件的方法,
}];
[_pageCon setViewControllers:[NSArray arrayWithObject:[self pageControllerAtIndex:_tagIndex]] direction:UIPageViewControllerNavigationDirectionReverse animated:YES completion:nil];
}
复制代码
这里咱们要注意两点: 1.开始滑动和结束滑动时的事件,当开始滑动的时候,咱们若是设置了自动轮播,就要先中止轮播,优先响应滑动事件,防止出现滑动和轮播冲突问题. 2.当滑到最后一页的时候,咱们的代理方法中要给出第0页当成下一页,当滑到第一页再往回滑动的时候,咱们要将最后一页当成上一页,这样就作到了循环滑动了.编码
//返回下一个页面
-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController{
NSInteger index= [_controlls indexOfObject:viewController];
NSLog(@"viewControllerAfterViewController-->%lu",index);
if(index==(_imageArr.count-1)){
index=0;
}else{
index++;
}
return [self pageControllerAtIndex:index];
}
//返回前一个页面
-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController{
//判断当前这个页面是第几个页面
NSInteger index=[_controlls indexOfObject:viewController];
NSLog(@"viewControllerBeforeViewController-->%lu",index);
//若是是第一个页面
if(index==0){
index=_imageArr.count-1;
}else{
index--;
}
return [self pageControllerAtIndex:index];
}
//根据tag取出内容页面
-(UIViewController*)pageControllerAtIndex:(NSInteger)index{
if(_controlls!=nil&&_controlls.count!=0){
UIViewController *con=_controlls[index];
return con;
}
return nil;
}
//结束滑动的时候触发
-(void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray<UIViewController *> *)previousViewControllers transitionCompleted:(BOOL)completed{
NSInteger index=[_controlls indexOfObject:pageViewController.viewControllers[0]];
_tagIndex=index;
[_indicator setCurrentPage:_tagIndex];
if(isAuto){//判断轮播是否开启,若是已开启,从新启动定时器
[self openAuto];
}
}
//开始滑动的时候触发
-(void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray<UIViewController *> *)pendingViewControllers{
[self closeAuto];
}
复制代码
为了方便对外部调用,提供了开启和关闭定时器的两个方法atom
//开启定时器
-(void)openAuto{
_isAuto=true;
//开启自动轮播
ALWk(weakSelf);
_timeZ=[NSTimer scheduledTimerWithTimeInterval:5 repeats:YES block:^(NSTimer * _Nonnull timer) {
NSLog(@"定时切换--%lu",_tagIndex);
weakSelf.tagIndex++;
if(weakSelf.tagIndex>(weakSelf.imageArr.count-1)){
weakSelf.tagIndex=0;
}
[_indicator setCurrentPage:weakSelf.tagIndex];
[weakSelf.pageCon setViewControllers:[NSArray arrayWithObject:[weakSelf pageControllerAtIndex:weakSelf.tagIndex]] direction:UIPageViewControllerNavigationDirectionReverse animated:YES completion:nil];
}];
}
//关闭定时器
-(void)closeAuto{
if(_timeZ){
_isAuto=false;
[_timeZ invalidate];
_timeZ=nil;
}
}
复制代码
至此,咱们的核心代码就写完了,接下来咱们只须要随便在个控制器中引入bannerView便可spa
先来张效果图吧设计
代码已上传github-->Banner