iOS可以改变滚动方向的滚动轮播图

42 篇文章 0 订阅

简介

  • 广告无限轮播图都很常见,创建三个UIImageView添加到就能达到无限轮播的效果(其实两张也可以,但是十分麻烦),本示例中有三种模式可以设定往左滚动,往右滚动,或者根据手动滑屏的方向随意改变其滚动的方向.并且不仅考虑到三张以上的图片轮播,也考虑了三张一下或者没有图片的情况.

原理

  • 默认设置UIScrollView偏移量让中间的UIImageView展示第一张图片.
  • 开启定时器时,如果设置的滚动标记是往左滚动,那么就在定时器事件中给右边的UIImageView设置当前图片的下一张图片,然后执行设置UIScrollViewcontentOffset让右边的UIImageView展示到屏幕中,当动画结束后把图片展示到中间的UIImageView,造成轮播的假象;如果是往右滚动类似,设置上一张图片到左边的UIImageView上,然后动画完成设置到中间的UIImageView上,主要定时器代码如下:
 //定时器事件
- (void)changeOffset {
   switch (self.scrollMode) {
       case LeftScrollMode: {
           [self scrollToLeft];
       }
           break;
       case RightScrollMode:
           [self scrollToRight];
           break;
           
       default:
           [self scrollWithAutomaticMode];
           break;
   }
   
}
- (void)scrollWithAutomaticMode{
   if(self.isToLeft){
       [self scrollToLeft];
   }else{
       [self scrollToRight];
   }
}
//往左滚
- (void)scrollToLeft {
   _currentPage ++;
   //如果是最后一个图片,让其成为第一个
   if (_currentPage >= _imagesNameArray.count) {
       _currentPage = 0;
   }
   //给右边的视图设置下一张图片
   UIImageView *rightImageView = _imageViewsArray[2] ;
   [rightImageView setImage:[UIImage imageNamed:_imagesNameArray[_currentPage]]];
   //滑动的过程中是设置到右边的视图上,滑动完成够设置到第一个视图上,造成一个无限滑动的假象
   [UIView animateWithDuration:_animationInterval animations:^{
         _mainScrollView.contentOffset = CGPointMake(_widthOfView*2, 0);
   } completion:^(BOOL finished) {
       //位移动画完成时,迅速的将图片设置到中间视图,并修改偏移量显示中间视图
       UIImageView * mainImageView = _imageViewsArray[1];
       [mainImageView setImage:[UIImage imageNamed:_imagesNameArray[_currentPage]]];
       _mainScrollView.contentOffset = CGPointMake(_widthOfView, 0);
   }];
    _imageViewPageControl.currentPage = _currentPage;
}
//往右滚
- (void)scrollToRight {
   _currentPage --;
   if (_currentPage < 0) {
       _currentPage = _imagesNameArray.count-1;
   }
   UIImageView *leftImageView = _imageViewsArray[0] ;
   [leftImageView setImage:[UIImage imageNamed:_imagesNameArray[_currentPage]]];
   [UIView animateWithDuration:_animationInterval animations:^{
       _mainScrollView.contentOffset = CGPointMake(0, 0);
   } completion:^(BOOL finished) {
       //位移动画完成时,迅速的将图片设置到中间视图,并修改偏移量显示中间视图
       UIImageView * mainImageView = _imageViewsArray[1];
       [mainImageView setImage:[UIImage imageNamed:_imagesNameArray[_currentPage]]];
       _mainScrollView.contentOffset = CGPointMake(_widthOfView, 0);
   }];
    _imageViewPageControl.currentPage = _currentPage;
}
  • 手动拖动时,由于RunLoop切换了模式,这时定时器将暂停,刚好我们可以处理拖动事件.将要拖动时会调用UIScrollView代理方法scrollViewWillBeginDragging,这里面由于我们不知道是往左边拖动还是往右边拖动,所以要在这里设置左边和右边的UIImageView对应当前展示图片的上一张图片和下一张图片.关键代码如下:
//手将要拽动的时候
-(void) scrollViewWillBeginDragging:(UIScrollView *)scrollView{
    //由于此时还不知道是王左拖还是往右拖动,所以就把三个视图都设置上对应的图片
    UIImageView *leftImageView = _imageViewsArray[0] ;
    NSInteger leftIndex = _currentPage - 1;
    if (leftIndex < 0) {
        leftIndex = _imagesNameArray.count - 1;
    }
    [leftImageView setImage:[UIImage imageNamed:_imagesNameArray[leftIndex]]];
    
    UIImageView *rightImageView = _imageViewsArray[2] ;
    NSInteger rightIndex = _currentPage + 1;
    if (rightIndex >= _imagesNameArray.count) {
        rightIndex = 0;
    }
    [rightImageView setImage:[UIImage imageNamed:_imagesNameArray[rightIndex]]];
}
  • 手完成拽动,并停止滚动时会调用scrollViewDidEndDecelerating代理方法,这时可以根据偏移量判断是往左边滑动还是右边滑动了,如果是往左边滑动就将下一张图片设置到中间的UIImageView上,并设置contentOffset来展示中间的UIImageView,造成左滑的假象;如果是往右边滑动则将上一张图片设置到中间的UIImageView上,并设置contentOffset来展示中间的UIImageView,造成右滑的假象.滚动停止后Runloop会切回默认模式,定时器会立马重新工作,我们可以设置一个定时时间间隔后定时器重新开始工作,关键代码如下:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
    NSLog(@"%lf",scrollView.contentOffset.x);
     //往右边滑动,并且分页了
    if (scrollView.contentOffset.x == 0) {
        _currentPage--;
        if (_currentPage < 0) {
            _currentPage = _imagesNameArray.count-1;
        }
        //修改滚动方向
        if (self.scrollMode == AutomaticMode){
            self.toLeft = NO;
        }
    }
    //往左边滑动,并且分页了
    if (scrollView.contentOffset.x == _widthOfView * 2) {
        _currentPage++;
        if(_currentPage >= _imagesNameArray.count)
            _currentPage = 0;
        if (self.scrollMode == AutomaticMode){
            self.toLeft = YES;
        }
    }
    UIImageView *mainImagev = _imageViewsArray[1];
    [mainImagev setImage:[UIImage imageNamed:_imagesNameArray[_currentPage]]];
    self.mainScrollView.contentOffset = CGPointMake(_widthOfView, 0);
    _imageViewPageControl.currentPage = _currentPage;
    [self resumeTimer];
}
-(void)resumeTimer{
    //如定时器已经失效,就返回
    if (![_timer isValid]) {
        _timer = nil;
        return ;
    }
    //暂停一个定时器时间
    [_timer setFireDate:[NSDate dateWithTimeIntervalSinceNow: self.timerInterval]];
}
  • 其他一些就是一些细节要注意,如无限轮番时要防止脚标越界,设置向左或向右的标记,图片少于两张和没有图片时的处理,定时器循环引用的解除,已经定时器销毁的条件等等,具体可见demo.

相关demo示例

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值