利用UIPageViewController实现图片轮播(简单实用版本)

3 篇文章 0 订阅
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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本Demo使用UICollectionView实现自动无限轮功能。 主要功能: 1.实现自动轮,可修改轮的时间 2.轮图片可以来自本地,也可来自网络,通过单独的方法进行设置即可。对于加载网络图片时,Demo中使用了YYWebImage,也可自行替换成SDWebImage。 3.重写了和系统UIPageControl一样的功能,可用图片代替PageControl上的点点,也可自定义其颜色以及切换动画。 使用方法:使用方法比较简单。 /** * 加载本地图片Banner */ - (void)setupLocalBannerImageView { NSArray *array = @[@"1.png", @"2.png", @"3.png", @"4.png", @"5.png"]; FFBannerView *bannerVew = [FFBannerView bannerViewWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 200) locationImageArray:array]; bannerVew.timeInterval = 2.0; [self.view addSubview:bannerVew]; } /** * 加载网络图片Banner */ - (void)setupNetWorkBannerImageView { NSArray *array = @[@"http://i3.download.fd.pchome.net/t_960x600/g1/M00/07/09/oYYBAFMv8q2IQHunACi90oB0OHIAABbUQAAXO4AKL3q706.jpg", @"http://images.weiphone.net/attachments/photo/Day_120308/118871_91f6133116504086ed1b82e0eb951.jpg", @"http://benyouhuifile.it168.com/forum/macos/attachments/month_1104/110425215921926a173e0f728e.jpg", @"http://benyouhuifile.it168.com/forum/macos/attachments/month_1104/1104241737046031b3a754f783.jpg"]; FFBannerView *bannerVew = [FFBannerView bannerViewWithFrame:CGRectMake(0, 250, [UIScreen mainScreen].bounds.size.width, 200) netWorkImageArray:array placeHolderImage:nil]; bannerVew.timeInterval = 2.0; bannerVew.pageControlStyle = FFPageControlStyleMiddle; bannerVew.delegate = self; [self.view addSubview:bannerVew]; } 以上方式即可简单使用,如需自定义PageControl也可继承FFAbstractDotView,做些基本的设置即可。 gitHub下载地址:喜欢的朋友请给个星呗! 欢迎各位一起来讨论,有问题请发邮箱270452746@qq.com或者直接加我QQ:270452746进行讨论。谢谢!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值