美文网首页程序员iOS开发进阶iOS程序猿
如何实现一个无限循环的轮播图

如何实现一个无限循环的轮播图

作者: _誌念 | 来源:发表于2017-11-24 17:55 被阅读801次

    前言

    由于项目中使用第三方的轮播图出现了崩溃情况,同时也想减少项目的依赖性,所以想自己实现一个轮播图。实现这样一个轮播图,可以使用UICollectionView或者UIScrollView,当然UICollectionView实现起来更容易一些。

    原理

    实现一个无限循环的轮播图的主要难点是如何实现左右无限滑动,在知乎上搜的的答案 ios轮播图实现原理?

    1.方案一

    N张照片把contentsSize设置为N+2个图片的宽度,例子如下,两端填充如图,当处于一端时,且即将进入循环状态的时候,如第二张图,从状态1滑动到状态2,在滑动结束的时候,将当前的位置直接转到状态3,直接setContentOffset神不知鬼不觉,视觉上是循环的。

    方案一.jpg
    2.方案二

    用view数组存储当前需要轮播的内容,直接使用三个指针,分为左,中,右分别指向数组中的view。屏幕一直显示的是“中”指向的view。过程如下,以此不停地变换三个指针,实现效果上的轮播。这样有个缺陷,就是每次仅能滑动一页,没办法快速滑动以滑过两页。

    方案二.jpg
    3.方案三

    我们来看看SDCycleScrollView这个超过4000Star的第三方库是如何实现的。首先它也是用UICollectionView来实现的。

    - (void)setImagePathsGroup:(NSArray *)imagePathsGroup{
        _imagePathsGroup = imagePathsGroup;
        _totalItemsCount = self.infiniteLoop ? self.imagePathsGroup.count * 100 : self.imagePathsGroup.count;
        
    ······
    }
    

    它的实现方法比较暴力,直接将将CellIterm的数量设置为图片数量 x 100,然后:

      if (self.infiniteLoop) {
           targetIndex = _totalItemsCount * 0.5;
           [_mainView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:targetIndex inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
        }
    

    在初始化运行的时候,将UICollectionView滑动到CellIterm数量的中间页,在左右滑动,当滑动到左右两端边界时,再重新滚动到轮播页中间的位置。

    动手实现

    综合比较一下上面👆的三种方法,第一种方法容易理解,而且思路也比较清晰。所以我用第一种方法动手实现了一个轮播图。

    首先,设置iterm的数量为self.imageArray.count + 2

    - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
        /**只有是无限循环和数组个数大于1时,才能无限循环*/
        if (self.isinFiniteLoop && self.imageArray.count > 1) {
            return self.imageArray.count + 2;
        }else{
            return self.imageArray.count;
        }
    }
    

    然后,在下面👇的赋值部分,当支持无限轮播,并且图片数量大于1时,将UICollectionView滚动到第一个index,如果图片数量小于等于1时,就不让其进行滚动。

    - (void)setImageArray:(NSArray *)imageArray{
        ······
        if (_imageArray.count > 1) {
            _myCollection.scrollEnabled = YES;
            [self setIsAutoScroll:_isAutoScroll];
        }else{
            _myCollection.scrollEnabled = NO;
            [self setIsAutoScroll:NO];
        }
        [_myCollection reloadData];
        
        if (_isinFiniteLoop && _imageArray.count > 1) {
           [_myCollection scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:1 inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
        }
    }
    

    在滑动结束的时候,如果处在临界状态,当前索引是0时,就滑动到索引是self.imageArray.count的位置,当前索引是currentIndex == self.imageArray.count + 1时,就滑动到索引是0的位置。

    - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView{
        NSInteger currentIndex = [self currentIndex];
        if (self.isinFiniteLoop && self.imageArray.count > 1) {
            if (currentIndex == 0) {
                [_myCollection scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:self.imageArray.count inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
            }else if (currentIndex == self.imageArray.count + 1){
               [_myCollection scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:1 inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
            }
        }
    }
    

    最终效果如下,支持垂直和水平滚动:


    无限轮播图.gif

    文中的例子可以到GitHub下载

    相关文章

      网友评论

        本文标题:如何实现一个无限循环的轮播图

        本文链接:https://www.haomeiwen.com/subject/xibxbxtx.html