利用UIPageViewController實現圖片輪播(簡單實用版本)
阿新 • • 發佈:2019-02-03
tips
今天專案中用到了輪播的功能,本來想著去網上找個第三方的,後來想一下自己實現一個也是挺簡單的.於是就有了這篇文章
一. 需求分析
總結了一下,一個廣告輪播必須含有以下幾個功能;
- 頁面內容可以自定義;比如說可以是圖片輪播,也可以是其他view
- 可以實現定時輪播;
- 能處理輪播頁的點選事件;
- 滑動到最後一頁的時候再往下滑動可以到第一頁,第一頁再往回滑動可以到最後一頁
- 最好能封裝成一個view,便於日後的使用
確定好要實現的功能,又到了我們最開心的編碼環節.
二. 需求設計
本來我第一時間想到的是利用UiScrollview或者UiCollectionView等元件來實現,不過在以前一篇 仿今日頭條新聞分頁中文章中我講過一下他們和UIPageViewController的區別.所以今天我就選定UIPageViewController來當我們這次的主角啦!
程式碼實現
我們新建一個BannerView的自定義view,所有的邏輯程式碼就寫裡面啦.
1.首先我們確定一下需要的一些變數屬性,具體詳情看註釋就明白了(小編程式碼註釋寫的賊多)
@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;
2. 初始化我們需要的相關view和一下相關變數
-(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);
}];
}
3. 初始化一些頁面資料
主要是建立輪播頁以及輪播頁面裡面要新增的內容(這裡我們只要放一個圖片即可)
-(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];
}
4. 新增UIPageViewController代理
這裡我們要注意兩點:
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];
}
5. 定時器的方法
為了方便對外部呼叫,提供了開啟和關閉定時器的兩個方法
//開啟定時器
-(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即可
三. 測試效果
先來張效果圖吧
程式碼已上傳github–>Banner