1. 程式人生 > >利用UIPageViewController實現圖片輪播(簡單實用版本)

利用UIPageViewController實現圖片輪播(簡單實用版本)

tips

今天專案中用到了輪播的功能,本來想著去網上找個第三方的,後來想一下自己實現一個也是挺簡單的.於是就有了這篇文章

一. 需求分析

總結了一下,一個廣告輪播必須含有以下幾個功能;

  1. 頁面內容可以自定義;比如說可以是圖片輪播,也可以是其他view
  2. 可以實現定時輪播;
  3. 能處理輪播頁的點選事件;
  4. 滑動到最後一頁的時候再往下滑動可以到第一頁,第一頁再往回滑動可以到最後一頁
  5. 最好能封裝成一個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