利用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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值