前言

市面上绝大部分的APP被打开之后映入眼帘的都是一个美轮美奂的轮播器,所以能做出一个符合需求、高效的轮播器成为了一个程序员的必备技能。所以今天的这篇博客就来谈谈轮播器这个看似简单的控件其中蕴含的道理。

正文

    首先我们来分析一下该如何去实现一个类似下图的轮播器(图片数量、URL由服务器返回):

    

     策略一:UIScrollView->UIImageView->NSTimer轮询 这算是常规的策略,但是如果仔细想想,如果服务器返回给你50图片是不是就需要创建50个UIImageView来做容器。这种性能肯定不是最优的。其次所有的UIImageView是按照次序排列,脑补一下如果到最后一张图片要重新回到第一张图片你的话,UIScrollView会被升拉到第一个位置。效果太差!

    策略二:想想UITableViewCell的重复利用,我们也可以重复利用其中的UIImageView。对于我们来说轮播器三个UIImageView就足够用了,分为当前视野中的CenterImageView、前一张LeftImageView、后一张RightImageView。不同的是他们之间的图片切换,下面我们就尝试去做高效的轮播器。

代码实现

  1. 初始化所需控件:

  

  2.写一个专门控制没次滑动结束去计算左中右三张序号并加载成对应的图片。

 /** 这里我起名叫reloadAllImageView */

 -(void)reloadAllImageView{

     CGPoint offset = _backScrollView.contentOffset;                       /** 获取到scroll的X轴偏移量 */

        if (offset.x ==  * DeviceWidth){                      /** 这里有两种边界情况要处理 (1).由first—>last (2)last->first */

         /** (2) */

             _centerImageIndex        = (_centerImageIndex + )%;          /** 3代表图片的数量,这里要主页类型的强转换。_centerImageIndex(NSUInteger)用于记录当前图片序号*/

             _pageControl.currentPage = (_pageControl.currentPage + )%;

         }

         else if (offset.x == ){

             /** (1) */

           if (_centerImageIndex == ) {                        /** 一种特殊情况 当_centerImageIndex等于0的时候 去计算(_centerImageIndex - 1) % 3并不是我们想要的结果 */

               _centerImageIndex = ;                          /** 尝试了很久,计算类型转换也就只有三张图片会有问题。如果有兴趣的朋友可以进行深入研究 */

           }                                      /** -1 % 3 = 0   如果都是有符号的结果是-1,如果按照无符号处理的话结果是0。难道计算过程应该先向前借位再进行计算? */

           _centerImageIndex        = (_centerImageIndex - ) % ;    

           _pageControl.currentPage = (_pageControl.currentPage - )%;

         }

       _centerImageView.image         = [UIImage imageNamed:[NSString stringWithFormat:@"图%d.jpg",_centerImageIndex + ]];

       NSUInteger leftImageViewIndex  = (_centerImageIndex - )%;

       NSUInteger  rightImageViewIndex = (_centerImageIndex + )%;

       if (leftImageViewIndex ==  && _centerImageIndex == ) {          /** 同上暂时处理计算特殊情况 */ 

           leftImageViewIndex = ;

       }

       _leftImageView.image           = [UIImage imageNamed:[NSString stringWithFormat:@"图%d.jpg",leftImageViewIndex + ]];

       _rightImageView.image          = [UIImage imageNamed:[NSString stringWithFormat:@"图%d.jpg",rightImageViewIndex + ]];

 }

    3.现在轮播器应该可以在边界正常切换了。现在需要再加上一个计时器来自动滑动即可:

 /** 声明一个定时器 */   /** 用weak的原因:self如果强拥有了Timer,之后你要设置计时器的Traget和选择子selector的时候,Timer又会保留目标对象直到失效。产生保留环 */

 @property(nonatomic,weak)NSTimer * timer;

 /** 定时器初始化 */

    -(void)initTimer

    {

        self.timer = [NSTimer scheduledTimerWithTimeInterval:animationTime target:self selector:@selector(updateImageView:) userInfo:nil repeats:YES];

    }

   -(void)updateImageView:(NSTimer *)timer

   {

       [_backScrollView setContentOffset:CGPointMake(DeviceWidth*, ) animated:YES];

       [NSTimer scheduledTimerWithTimeInterval:0.4f target:self selector:@selector(scrollViewDidEndDecelerating:) userInfo:nil repeats:NO];

   }

 /** 计算加载所有图片然后移动的中间视野 */

   -(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{

       //重新加载图片

       [self reloadAllImageView];

       //移动到当前视野

       [_backScrollView setContentOffset:CGPointMake(DeviceWidth, )];

       //设置脚标

       _pageControl.currentPage = _centerImageIndex;

   }

  4.自此轮播器大概雏形已经搞定了。剩下的就是需要搞定计时器和用户滑动操作的互斥事件处理。

/**记录一个bool值用于确定滑动操作的愿意你。YES,计时器触发,NO则为用户触发*/

     ().计时器的触发事件中,肯定是由计时器触发的滑动。所以这里bool值为YES

  ().加载替换图片的时候我们要进行判断(如果是用户触发的时候我们要将计时器取消并从空为0)

    if (!bool) {

          [self.timer setFireDate:[NSDate dateWithTimeIntervalSinceNow:animationTime]];

      }

       bool = NO;

结尾

    由此轮播器就实现了,但是其中还是有问题需要解决<1>.限制必须要三张图片不然会crash <2>没有封装成单独的scrllview以供使用。后续可能会对这些问题加以思考并重新优化。也许尝试用UICollection来做也是个很好的想法。

最后经过写这篇博客也有一个目的,其实任何一个看似简单的功能要深入挖掘的话还是有很说知识的,也发现了自身的不足。最后如果各位大神们看到了博客有任何想法意见的欢迎下面留言。大家一起探讨一起进步。谢谢各位!

iOS开发那些事儿(一)轮播器的更多相关文章

  1. iOS开发UI篇—无限轮播(循环利用)

    iOS开发UI篇—无限轮播(循环利用) 一.无限轮播  1.简单说明 在开发中常需要对广告或者是一些图片进行自动的轮播,也就是所谓的无限滚动. 在开发的时候,我们通常的做法是使用一个UIScrollV ...

  2. iOS开发UI篇—无限轮播(新闻数据展示)

    iOS开发UI篇—无限轮播(新闻数据展示) 一.实现效果        二.实现步骤 1.前期准备 (1)导入数据转模型的第三方框架MJExtension (2)向项目中添加保存有“新闻”数据的pli ...

  3. iOS开发UI篇—无限轮播(循环展示)

    iOS开发UI篇—无限轮播(循环展示) 一.简单说明 之前的程序还存在一个问题,那就是不能循环展示,因为plist文件中只有五个数组,因此第一个和最后一个之后就没有了,下面介绍处理这种循环展示问题的小 ...

  4. iOS开发UI篇—无限轮播(功能完善)

    iOS开发UI篇—无限轮播(功能完善) 一.自动滚动 添加并设置一个定时器,每个2.0秒,就跳转到下一条. 获取当前正在展示的位置. [self addNSTimer]; } -(void)addNS ...

  5. IOS第六天(3:scrollView 图片轮播器)

    IOS第六天(3:scrollView 图片轮播器) #import "HMViewController.h" #define kImageCount 5 @interface H ...

  6. ios之无限 自动 图片轮播器的实现

    比较之前发布的手动无限图片轮播器进行了改进.实现了自动无限轮播的功能.比较适合团购标题分类下面的轮播器功能. 实现思路: * 开启一个定时器,把操作放入消息循环池.每隔一定时间,操作执行一次. * 注 ...

  7. 【iOS开发-55】图片轮播案例:scrollView的分页、滚动栏、利用代理控制定时器和Page Control以及多线程问题

    案例: (1)用storyboard布局,这里用了三样东西. --UIScrollView就是我们准备存放滚动图片的容器. --Page Control就是控制页数的那几个小点点.能够设置有多少个点. ...

  8. ios开发图片轮播器以及定时器小问题

    一:图片轮播器效果如图:能实现自动轮播,到最后一页时,轮播回来,可以实现拖拽滚动 二:代码: #import "ViewController.h" ; @interface Vie ...

  9. ios 学习 广告图片轮播器

    // // ViewController.m // 图片轮播器 // // Created by zjj on 15/5/23. // Copyright (c) 2015年 zjj. All rig ...

随机推荐

  1. JS闭包(一)

    闭包是指有权访问另一个函数作用域中的变量的函数. 创建闭包的常见方法:在一个函数内部创建另一个函数. 对彻底理解闭包,需要知道如何创建作用域链以及作用域链有什么作用的细节. 闭包的功能: 保存函数执行 ...

  2. Android实现点击事件的4种方式

    一.通过在activity_main.xml中,按钮button控件中添加onclick事件实现 在   activity_main.xml 对应的按钮Button中加入下面红色事件 <Butt ...

  3. 使用LAMP创建基于wordpress的个从博客网站

    参考: http://blog.csdn.net/ck_boss/article/details/27866117 一.mysql配置 1.安装mysql yum install mysql-serv ...

  4. Python之路第十一天,高级(3)-线程池

    线程池 简单的线程池的实现: import queue import threading import time class ThreadPool(object): def __init__(self ...

  5. python读取Excel

    import xlrd # 读取Excel文件 workbook = xlrd.open_workbook(r'E:\2015.xls') # 读取Excel的sheet名字 sheet_names ...

  6. HDU ACM 题目分类

    模拟题, 枚举1002 1004 1013 1015 1017 1020 1022 1029 1031 1033 1034 1035 1036 1037 1039 1042 1047 1048 104 ...

  7. phalcon

    phalcon 代码内在sql 内用Ad去取数据库内的ad表. osx上没问题, centos报找不到表. 应该是centos上mysql区分大小写,可改写mysql的配置.

  8. C++ Primer day 01

    1.标准输入与输出 #include<iostream> int main(){ int v1,v2; std::cout<<"Enter two numbers:& ...

  9. jQuery_基础

    一.jQuery与DOM对象的转换. 1.jQuery对象转换为DOM对象:$cr[0] 或 $cr.get(0) $cr为jQuery对象 2.DOM对象转换为jQuery对象:$(cr) cr为D ...

  10. 【关于微软的上一代模板引擎 T4引擎】

    导语:国内有名的动软代码生成器用的就是T4引擎......可以自己下载下来用用,批量生成固定模式的代码文件,十分有用........... 示例代码:示例代码__你必须懂的T4模板:浅入深出.rar ...