今天項目中用到了輪播的功能,原本想着去網上找個第三方的,後來想一下本身實現一個也是挺簡單的.因而就有了這篇文章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