iOS轮播图(OC版本)

轮播图在开发中经常用到。并且面试的时候也经常回问道。
其实最长问道的也就两点
1、内存优化
2、计时器问题
3、轮播实现方案

                             此轮播图以UIScrollView实现

先以第一点内存优化和实现方案来讲,如何去做内存优化?
图片在iOS设备中很占内存,所以每当遇到加载图片的时候需要格外注意,不要去加载一些不必要的图片。
首先应当想到要减少UIImageView在UIScrollView上加载。结合UITableView的特点:复用。所以至少应当创建三个UIImageView。


要以这种方式排列

实际上我们所展示的第1张图片在对应的ScrollView上应该是第2页。
并且重要的一点就是:所展示的图片一直是中间的。当滑到两边的图片后,要立刻重置到第二张。

两种代理实现方案

减速实现

    - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate 

滑动过程中

      - (void)scrollViewDidScroll:(UIScrollView *)scrollView

当使用结束拖拽的代理正常使用情况下其实是不会出现的问题的,但是当用户快速拖拽时,scrollview的偏移会出现问题。最好的方法便是实时计算偏移量

核心代码

        - (void)scrollViewDidScroll:(UIScrollView *)scrollView
  {
      [self reloadIndex];
  }



  //滑到中心,切记不能调用该动画,否则会触发代理
- (void)scrollCenter
{
      [self.mainScrollView setContentOffset:CGPointMake(CGRectGetWidth(self.mainScrollView.bounds), 0)];
      if (self.indexBack) {
          self.indexBack(self.index);
      }
  }



  //计算页数
    - (void)reloadIndex
  {
      if (self.imageArray && self.imageArray.count > 0)
      {
          CGFloat pointX = self.mainScrollView.contentOffset.x;

          //此处的value用于边缘判断,当imageview距离两边间距小于1时,触发偏移
          CGFloat Value = 0.2f;

          if (pointX > 2 * CGRectGetWidth(self.mainScrollView.bounds) - Value) {
              self.index = (self.index + 1) % self.imageArray.count;
        
    } else if (pointX < Value) {
        self.index = (self.index + self.imageArray.count - 1) % self.imageArray.count;
    }

}

  }

  //重写index的set方法
  - (void)setIndex:(NSInteger)index
  {
      _index = index;
      NSInteger totalCount = self.imageArray.count;
      NSInteger   leftIndex = (self.index+totalCount-1)%totalCount;
      NSInteger   rightIndex = (self.index+1)%totalCount;

      [self.leftImageView setImage:[UIImage imageNamed:self.imageArray[leftIndex]]];
      [self.midImageView setImage:[UIImage imageNamed:self.imageArray[self.index]]];
      [self.rightImageView setImage:[UIImage imageNamed:self.imageArray[rightIndex]]];

      [self scrollCenter];
  }

关于计算页数说明:
假如有4张图片排序为,4|0|1|2|3,其实严格说此排序像一个环形数列,所以leftIndex和rightIndex的公式相当于去计算指定页数的前一个和后一个数字

  .h 文件
      @interface MCScrollView : UIView


  @property (nonatomic, copy) void(^indexBack)(NSInteger pageIndex);      //页数回调

  @property (nonatomic, copy) NSArray *imageArray;    //存储图片数据

  @property (nonatomic, assign) NSInteger index;      //当前第几页,默认为0(0为第一页,如果制定页数需要加1)

  @end

定时器添加

  .h文件添加
  @property (nonatomic, assign) NSTimeInterval    duration;       //时长

实现

   - (void)setDuration:(NSTimeInterval)duration
    {
        _duration = duration;
      if (duration > 0.0) {
    
          self.timer = [NSTimer scheduledTimerWithTimeInterval:duration target:self selector:@selector(changeNext) userInfo:nil repeats:YES];
          [self.timer setFireDate:[NSDate dateWithTimeIntervalSinceNow:duration]];
      }
  }


  - (void)changeNext
  {
      [self.mainScrollView setContentOffset:CGPointMake(2*CGRectGetWidth(self.mainScrollView.bounds), 0) animated:YES];
  }



  - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
  {
      [self.timer setFireDate:[NSDate distantFuture]];
  //[NSDate distantFuture]表示暂停计时
  }



  - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
  {
      [self.timer setFireDate:[NSDate dateWithTimeIntervalSinceNow:self.duration]];
  //
  }

[NSDate dateWithTimeIntervalSinceNow:self.duration]表示在当前时间的几秒后开始计时,优点是不会立即执行计时器
Demo地址:https://github.com/HeartbeatT/MCScrollView.git

你可能感兴趣的:(iOS轮播图(OC版本))