iOS开发那些事儿(一)轮播器

前言

市面上绝大部分的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 == 2 * DeviceWidth){                      /** 这里有两种边界情况要处理 (1).由first—>last (2)last->first */

        /** (2) */

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

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

     }

      else if (offset.x == 0){

    /** (1) */

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

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

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

  _centerImageIndex        = (_centerImageIndex - 1) % 3;    

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

    }

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

   NSUInteger leftImageViewIndex  = (_centerImageIndex - 1)%3;

   NSUInteger  rightImageViewIndex = (_centerImageIndex + 1)%3;

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

   leftImageViewIndex = 2;

    }

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

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

}
    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*2, 0) 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, 0)];

  //设置脚标

  _pageControl.currentPage = _centerImageIndex;

  }

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

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

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

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

    if (!bool) {

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

   }

   bool = NO;

结尾

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

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

时间: 2024-09-28 16:38:53

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

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

iOS开发UI篇—无限轮播(功能完善) 一.自动滚动 添加并设置一个定时器,每个2.0秒,就跳转到下一条. 获取当前正在展示的位置. 1 [self addNSTimer]; 2 } 3 4 -(void)addNSTimer 5 { 6 // NSTimer timerWithTimeInterval:<#(NSTimeInterval)#> target:<#(id)#> selector:<#(SEL)#> userInfo:<#(id)#> repe

IOS 05 UIScrollView介绍 图片轮播器

移动设备的屏幕?大?小是极其有限的,因此直接展?示在?用户眼前的内容也相当有限 当展?示的内容较多,超出?一个屏幕时,?用户可通过滚动?手势来查看屏幕以外的内容 普通的UIView不具备滚动功能,不能显?示过多的内容 UIScrollView是?一个能够滚动的视图控件,可以?用来展?示?大量的内容,并且可以通过滚 动查看所有的内容 在IOS中UIScrollView这个控件还是比较常用和重要的. 很多时候,我们想在UIScrollView正在滚动 或 滚动到某个位置 或者 停?止滚动 时做?一些

iOS学习 - scrollView(图片轮播器)

// // YJViewController.m // 07-图片轮播器 // // Created by JACKY-MAC on 15-6-18. // Copyright (c) 2015年 www.train.com. All rights reserved. // #import "YJViewController.h" #define kImageCount 5 @interface YJViewController ()<UIScrollViewDelegate&g

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

一.无限轮播  1.简单说明 在开发中常需要对广告或者是一些图片进行自动的轮播,也就是所谓的无限滚动. 在开发的时候,我们通常的做法是使用一个UIScrollView,在UIScrollView上面添加多个imageView,然后设置imageView的图片,和scrollView的滚动范围. 以前的做法: 一般而言,轮播的广告或者是图片数量都不会太多(3~5张).所以,并不会太多的去考虑性能问题.但是如果图片过多(比如有16张图片,就需要创建16个imageView),那么就不得不考虑性能问题

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

案例: (1)用storyboard布局,这里用了三样东西. --UIScrollView就是我们准备存放滚动图片的容器. --Page Control就是控制页数的那几个小点点.可以设置有多少个点,当前点和其他点的颜色等.注意它和UIScrollView是平级的,不是它的子视图. --还有一个textView是带有滚动的,用来测试多线程的.暂且随意拖放在页面中即可. (2)在ViewController.m中 --借助之前的scrollView属性,设置滚动范围 --借助新学习的scrollV

iOS开发-关于广告轮播页自动跳转controller的问题

最近在项目中遇到这么一个场景,首页的广告轮播页需要根据服务端的配置,跳转到不通的界面. 首先想到的就是反射,对反射真心的不太熟,所以在网上查查资料,用下面的方法实现的. -(void)remoteNotificationDictionary:(CHomeAdModel *)model { NSString *strClassName = model.strTarget; NSDictionary *dicParams = model.dicParams; // 根据字符串反射出我们想要的类,并初

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

一.简单说明 之前的程序还存在一个问题,那就是不能循环展示,因为plist文件中只有五个数组,因此第一个和最后一个之后就没有了,下面介绍处理这种循环展示问题的小技巧. 方法一:使用一个for循环,循环200次,创建200*=1000个模型,且默认程序启动后处在第100组的位置,向前有500个模型,向后也有500个模型,产生一种循环展示的假象. 代码如下: 1 // 2 // YYViewController.m 3 // 07-无限滚动(循环利用) 4 // 5 // Created by ap

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

一.实现效果        二.实现步骤 1.前期准备 (1)导入数据转模型的第三方框架MJExtension (2)向项目中添加保存有“新闻”数据的plist文件 (3)导入用到的图片素材 2.步骤和代码 (1)新建一个数据模型 该模型的代码设计如下: YYnews.h文件 1 // 2 // YYnews.h 3 // 08-无限滚动(新闻数据展示) 4 // 5 6 #import <Foundation/Foundation.h> 7 8 @interface YYnews : NSO

iOS开发UI篇—无限轮播

  转载自 http://www.cnblogs.com/wendingding/p/3890953.html 一.自动滚动 添加并设置一个定时器,每个2.0秒,就跳转到下一条. 获取当前正在展示的位置. 1 [self addNSTimer]; 2 } 3 4 -(void)addNSTimer 5 { 6 // NSTimer timerWithTimeInterval:<#(NSTimeInterval)#> target:<#(id)#> selector:<#(SE

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

#import "HMViewController.h" #define kImageCount 5 @interface HMViewController () <UIScrollViewDelegate> @property (nonatomic, strong) UIScrollView *scrollView; @property (nonatomic, strong) UIPageControl *pageControl; @property (nonatomic