前言

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

正文

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

    

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

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

代码实现

  1. 初始化所需控件:

  

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

  1. /** 这里我起名叫reloadAllImageView */
  2.  
  3. -(void)reloadAllImageView{
  4.  
  5.     CGPoint offset = _backScrollView.contentOffset;            /** 获取到scroll的X轴偏移量 */
  6.  
  7.     if (offset.x == * DeviceWidth){                      /** 这里有两种边界情况要处理 (1).由first—>last (2)last->first */
  8.  
  9.         /** (2) */
  10.  
  11.      _centerImageIndex = (_centerImageIndex + )%;       /** 3代表图片的数量,这里要主页类型的强转换。_centerImageIndex(NSUInteger)用于记录当前图片序号*/
  12.  
  13.      _pageControl.currentPage = (_pageControl.currentPage + )%;
  14.  
  15.      }
  16.  
  17.      else if (offset.x == ){
  18.  
  19.     /** (1) */
  20.  
  21.   if (_centerImageIndex == ) {                       /** 一种特殊情况 当_centerImageIndex等于0的时候 去计算(_centerImageIndex - 1) % 3并不是我们想要的结果 */
  22.  
  23.   _centerImageIndex = ;                         /** 尝试了很久,计算类型转换也就只有三张图片会有问题。如果有兴趣的朋友可以进行深入研究 */
  24.  
  25.   }                                      /** -1 % 3 = 0 如果都是有符号的结果是-1,如果按照无符号处理的话结果是0。难道计算过程应该先向前借位再进行计算? */
  26.  
  27.   _centerImageIndex = (_centerImageIndex - ) % ;    
  28.  
  29.   _pageControl.currentPage = (_pageControl.currentPage - )%;
  30.  
  31.     }
  32.  
  33.   _centerImageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"图%d.jpg",_centerImageIndex + ]];
  34.  
  35.    NSUInteger leftImageViewIndex = (_centerImageIndex - )%;
  36.  
  37.    NSUInteger rightImageViewIndex = (_centerImageIndex + )%;
  38.  
  39.   if (leftImageViewIndex == && _centerImageIndex == ) {          /** 同上暂时处理计算特殊情况 */ 
  40.  
  41.    leftImageViewIndex = ;
  42.  
  43.    }
  44.  
  45.   _leftImageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"图%d.jpg",leftImageViewIndex + ]];
  46.  
  47.   _rightImageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"图%d.jpg",rightImageViewIndex + ]];
  48.  
  49. }

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

  1. /** 声明一个定时器 */ /** 用weak的原因:self如果强拥有了Timer,之后你要设置计时器的Traget和选择子selector的时候,Timer又会保留目标对象直到失效。产生保留环 */
  2.  
  3. @property(nonatomic,weak)NSTimer * timer;
  4.  
  5. /** 定时器初始化 */
  6.  
  7.    -(void)initTimer
  8.  
  9.    {
  10.  
  11.    self.timer = [NSTimer scheduledTimerWithTimeInterval:animationTime target:self selector:@selector(updateImageView:) userInfo:nil repeats:YES];
  12.  
  13.    }
  14.  
  15.   -(void)updateImageView:(NSTimer *)timer
  16.  
  17.   {
  18.  
  19.   [_backScrollView setContentOffset:CGPointMake(DeviceWidth*, ) animated:YES];
  20.  
  21.    [NSTimer scheduledTimerWithTimeInterval:0.4f target:self selector:@selector(scrollViewDidEndDecelerating:) userInfo:nil repeats:NO];
  22.  
  23.   }
  24.  
  25. /** 计算加载所有图片然后移动的中间视野 */
  26.  
  27.   -(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
  28.  
  29.    //重新加载图片
  30.  
  31.   [self reloadAllImageView];
  32.  
  33.   //移动到当前视野
  34.  
  35.    [_backScrollView setContentOffset:CGPointMake(DeviceWidth, )];
  36.  
  37.   //设置脚标
  38.  
  39.   _pageControl.currentPage = _centerImageIndex;
  40.  
  41.   }

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

  1. /**记录一个bool值用于确定滑动操作的愿意你。YES,计时器触发,NO则为用户触发*/
  2.  
  3. ().计时器的触发事件中,肯定是由计时器触发的滑动。所以这里bool值为YES
  4.  
  5.   ().加载替换图片的时候我们要进行判断(如果是用户触发的时候我们要将计时器取消并从空为0
  6.  
  7.     if (!bool) {
  8.  
  9.    [self.timer setFireDate:[NSDate dateWithTimeIntervalSinceNow:animationTime]];
  10.  
  11.    }
  12.  
  13.    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. Visual Studio - 提升幸福感的N个快捷键

    现代化IDE给程序猿提供了极大的方便,掌握一些优秀的开发工具,使我们写代码时有行云流水般的快感. VS作为宇宙最强没有之一的IDE,用起来也是好幸福.下面是我最常用的快捷键,已经印在手指上,每次好像不 ...

  2. DataList、Repeater、GridView中的Checkbox取值问题

    先看页面代码 <asp:DataList id="DataList1" runat="server" Width="100%" Rep ...

  3. ASP.NET的Application简介1

    ASP.NET中的Application 1. Application是用于保存所有用户共有的信息.在ASP时代,如果要保存的数据在应用程序生存期内不会或者很少改变,那么使用Application是理 ...

  4. nginx 搭建rtmp流媒体所用资源

    Linux: 1.nginx安装包,自行下载. 2.nginx_mod_h264_streaming-2.2.7下载 3.nginx-rtmp-module-master下载 Windows: ngi ...

  5. hdu1215七夕节

    Problem Description 七夕节那天,月老来到数字王国,他在城门上贴了一张告示,并且和数字王国的人们说:"你们想知道你们的另一半是谁吗?那就按照告示上的方法去找吧!" ...

  6. 关于char/varchar(n)中n的探究:字符数or字节数

    [问题来源]将设计的数据库表展示的时候,yu哥问我,你的那个top_info字段定义的类型是varchar(100),为什么是100呢,这100的长度能存多少个中文? 当时的想法就是,这个100能存多 ...

  7. Bootstrap的响应式,当文字超过div长度,换行问题的处理!

    (1)overflow: hiddenoverflow 属性规定当内容溢出元素框时发生的事情.这个属性定义溢出元素内容区的内容会如何处理.hidden 表示内容会被修剪,并且剪掉的内容是不可见的. ( ...

  8. Sticks(Central Europe 1995) (DFS)

    Sticks(Central Europe 1995) Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d &am ...

  9. 纯js实现积木(div)拖动效果

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. Android IntentService 与Alarm开启任务关闭任务

    1:MyService public class MyService extends IntentService{ AlarmManager alarmManager = null; PendingI ...