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

tips

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

一. 需求分析

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

  1. 頁面內容能夠自定義;好比說能夠是圖片輪播,也能夠是其餘view
  2. 能夠實現定時輪播;
  3. 能處理輪播頁的點擊事件;
  4. 滑動到最後一頁的時候再往下滑動能夠到第一頁,第一頁再往回滑動能夠到最後一頁
  5. 最好能封裝成一個view,便於往後的使用

肯定好要實現的功能,又到了咱們最開心的編碼環節.bash

二. 需求設計

原本我第一時間想到的是利用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. 初始化一些頁面數據

主要是建立輪播頁以及輪播頁面裏面要添加的內容(這裏咱們只要放一個圖片便可)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];
    
}
複製代碼
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. 定時器的方法

爲了方便對外部調用,提供了開啓和關閉定時器的兩個方法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

相關文章
相關標籤/搜索