美文网首页
iOS基于UICollectionView实现一个无限轮播

iOS基于UICollectionView实现一个无限轮播

作者: iOS_dev | 来源:发表于2019-07-27 11:09 被阅读0次

    欢迎下载:项目地址

    网上这么多造好的轮子,为啥自己要去造个轮子?

    其实自己在造轮子之前也看了网上的一些实现方案:

    1. UIScrollView与N + 2个UIImageView
    2. UIScrollView与1 + 2个UIImageView
    3. UICollectionView与N乘以一个很大的数字,然后初始化的时候滚到中间位置
    

    这些方案多多少少都会有一些问题:

    方案一:如果有大量的图片需要显示就会造成内存的暴增,严重影响APP的性能
    方案二:虽然不会造成内存暴增,但是实现起来也是比较繁琐,需要反复的调整各个UIImageView的位置,计算现在显示的是哪一个图片,代码体积较为庞大
    方案三:主要的问题是实现不够优雅
    

    下面说说我的实现

    先说说为啥选用UICollectionView,它最大的一个优点就是cell的复用机制,这个机制保证了不论我需要显示多少张图片,它在内存中实际就创建两个cell
    原理:返回N + 2个cell,indexPath.row == 0的cell展示最后一张图片,indexPath.row == N + 1的cell展示第一张图片,这样就形成了一个循环,当滚动到indexPath.row == 0时偏移到indexPath.row == N的cell;当滚动到indexPath.row == N + 1时偏移到indexPath.row == 1的cell
    完整实现代码如下:

    //
    //  DABannerView.m
    //  DABannerView
    //
    //  Created by linfeng wang on 2019/7/22.
    //  Copyright © 2019 linfeng wang. All rights reserved.
    //
    
    #import "DABannerView.h"
    #import "DABannerCollectionViewCell.h"
    #import "DABannerFlowLayout.h"
    
    #define random(r, g, b, a) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:(a)/255.0]
    #define randomColor random(arc4random_uniform(256), arc4random_uniform(256), arc4random_uniform(256), arc4random_uniform(256))
    
    @interface DABannerView ()<UICollectionViewDelegate,UICollectionViewDataSource>
    
    @property (nonatomic, strong) UICollectionView *collectionView;
    @property (nonatomic, strong) UIPageControl *pageControl;
    @property (nonatomic, strong) NSTimer *timer;
    
    @end
    
    @implementation DABannerView {
        NSArray <UIColor *>*_colorArr;
    }
    
    - (instancetype)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            _colorArr = @[[UIColor redColor],[UIColor greenColor],[UIColor blueColor],[UIColor yellowColor]];
            [self addSubview:self.collectionView];
            [self addSubview:self.pageControl];
        }
        return self;
    }
    
    #pragma mark -- action
    - (void)timerAction:(NSTimer *)timer {
        NSIndexPath *indexPath = [self.collectionView indexPathsForVisibleItems].lastObject;
        NSIndexPath *nextPath = [NSIndexPath indexPathForItem:(indexPath.item + 1)%(self.urlStringForImageArr.count+2) inSection:indexPath.section];
        [self.collectionView scrollToItemAtIndexPath:nextPath atScrollPosition:UICollectionViewScrollPositionLeft animated:YES];
    }
    
    #pragma mark -- collectionView delegate and datasource
    - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
        return self.urlStringForImageArr.count + 2;
    }
    
    - (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
        DABannerCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"DABannerCollectionViewCell" forIndexPath:indexPath];
        if (indexPath.row == 0) {
            cell.backgroundColor = _colorArr.lastObject;
        }else if (indexPath.row ==_urlStringForImageArr.count + 1) {
            cell.backgroundColor = _colorArr.firstObject;
        }else {
            cell.backgroundColor = _colorArr[indexPath.row - 1];
        }
        return cell;
    }
    
    - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
        
    }
    
    #pragma mark -- scrollview delegate
    - (void)scrollViewDidEndDecelerating:(UIScrollView*)scrollView{
        CGFloat offsetX = scrollView.contentOffset.x;
        NSInteger page = offsetX / self.bounds.size.width;
        
        NSInteger itemsCount = [self.collectionView numberOfItemsInSection:0];
        if (page == 0) { // 第一页
            [self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:self.urlStringForImageArr.count inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
        } else if (page == itemsCount - 1) { // 最后一页
            [self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
        }
    }
    
    - (void)scrollViewDidEndScrollingAnimation:(UIScrollView*)scrollView{
        // 手动调用减速完成的方法
        [self scrollViewDidEndDecelerating:self.collectionView];
    }
    
    - (void)scrollViewDidScroll:(UIScrollView*)scrollView{
        CGFloat offsetX = scrollView.contentOffset.x;
        CGFloat page = offsetX / self.bounds.size.width;
        NSInteger itemsCount = [self.collectionView numberOfItemsInSection:0];
        if (page == 0) { // 第一页
            self.pageControl.currentPage = self.urlStringForImageArr.count - 1;
        } else if (page == itemsCount - 1) { // 最后一页
            self.pageControl.currentPage = 0;
        }else {
            self.pageControl.currentPage = page - 1;
        }
    }
    
    #pragma mark -- setter and getter
    - (UICollectionView *)collectionView {
        if (!_collectionView) {
            DABannerFlowLayout *layout = [[DABannerFlowLayout alloc] init];
            _collectionView = [[UICollectionView alloc] initWithFrame:self.frame collectionViewLayout:layout];
            _collectionView.showsHorizontalScrollIndicator = NO;
            _collectionView.bounces = NO;
            _collectionView.pagingEnabled = YES;
            _collectionView.showsVerticalScrollIndicator = NO;
            _collectionView.showsHorizontalScrollIndicator = NO;
            _collectionView.dataSource = self;
            _collectionView.delegate = self;
            [_collectionView registerNib:[UINib nibWithNibName:@"DABannerCollectionViewCell" bundle:nil] forCellWithReuseIdentifier:@"DABannerCollectionViewCell"];
        }
        return _collectionView;
    }
    
    - (UIPageControl *)pageControl {
        if (!_pageControl) {
            CGFloat width = 120;
            CGFloat height = 20;
            CGFloat pointX = ([UIScreen mainScreen].bounds.size.width - width) / 2;
            CGFloat pointY = self.bounds.size.height - height;
            _pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(pointX, pointY, width, height)];
            _pageControl.numberOfPages = self.urlStringForImageArr.count;
            _pageControl.userInteractionEnabled = NO;
            _pageControl.pageIndicatorTintColor = [UIColor lightTextColor];
            _pageControl.currentPageIndicatorTintColor = [UIColor whiteColor];
        }
        return _pageControl;
    }
    
    - (void)setUrlStringForImageArr:(NSArray *)urlStringForImageArr {
        _urlStringForImageArr = urlStringForImageArr;
        self.pageControl.currentPage = 0;
        self.pageControl.numberOfPages = urlStringForImageArr.count;
        [self.collectionView reloadData];
        //滚动到中间位置
        NSIndexPath* indexPath = [NSIndexPath indexPathForItem:1 inSection:0];
        [self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionLeft animated:NO];
        _timer = [NSTimer timerWithTimeInterval:2 target:self selector:@selector(timerAction:) userInfo:nil repeats:YES];
        [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSDefaultRunLoopMode];
        _timer.fireDate = [NSDate dateWithTimeIntervalSinceNow:2];
    }
    
    @end
    
    

    相关文章

      网友评论

          本文标题:iOS基于UICollectionView实现一个无限轮播

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