ios

来源:互联网 发布:游戏美工是什么专业 编辑:程序博客网 时间:2024/06/06 02:49

网上找到了使用scrollView实现的无限轮播的方法,需要自己写一个缓存池,不过没有找到collectionView的方法,在这边使用CollectionView实现,下面的demo本人跑起来完全没问题,如有问题的地方,希望大家指出来(里面有一些方法是自己封装的基类,会注入说明)。

基本思路:在原有的数组最前面再插入一个最后的数据,在最后面插入一个最前面的数据,这有点类似于将 12345 变成 5123451

代码:

首先是实现collectionView的数据源方法:

//每个section有多少个item- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{    return self.circularRollViewArray.count;}//返回每个cell,这里的CirularRollViewCell是一个自定义cell,里面就是一个简单的imageview,有想法的同学可以做的复杂一点。- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{    CirularRollViewCell *cell = nil;    //从缓存池中取cell。    cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([CirularRollViewCell class]) forIndexPath:indexPath];    //这里的viewUpdateWithModel方法是我自己写的协议方法,就是通过数据更新视图的方法,这边你们知道就行了。    if ([cell respondsToSelector:@selector(viewUpdateWithModel:)]) {        [cell viewUpdateWithModel:self.circularRollViewArray[indexPath.item]];    }    //这一步是实现代理的方法,不写对整个轮播的实现没影响。    if ([cell respondsToSelector:@selector(setDelegate:)]) {        [cell performSelector:@selector(setDelegate:) withObject:self];    }    return cell;}

然后在viewUpdateWithModel方法中实现重组数组,在重组之后重加在,然后将视图跳到重组过后的数组的第二个数据,即原本的第一个数据,然后启动定时器

    [self.circularRollViewArray addObject:[self.imageArray lastObject]];    [self.circularRollViewArray addObjectsFromArray:self.imageArray];    [self.circularRollViewArray addObject:[self.imageArray firstObject]];    [self.circularRollView reloadData];    NSIndexPath *indexPath = [NSIndexPath indexPathForItem:1 inSection:0];    [self.circularRollView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO];    //开始定时器其实就是把上一次的定时器销毁,然后再重新创建一个新的定时器    [self startTimer];

下面的很关键,就是如何跳转的逻辑

//由于collectionView没有类似于viewDidload这样的方法,只能寄托于下面的这个代理方法。这个代理方法是在cell将要出现的时候就调用一次。- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath{    //记录将要出现的cell,来作为下面的是否换cell做判断。    self.nextItem = indexPath.item;}//这个方法是上一个视图完全消失,就调用一次- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath{    //按照5123451来做判断,如果当前的内容是第一个5,则直接无动画的转到倒数第二个的5。如果当前内容是最后一个1,则无动画的跳转到正数第二个1。    if (indexPath.item == 1 && self.nextItem == 0) {        NSIndexPath *tmpIndexPath = [NSIndexPath indexPathForItem:(self.circularRollViewArray.count - 2) inSection:0];        [self.circularRollView scrollToItemAtIndexPath:tmpIndexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO];    }else if ((indexPath.item == (self.circularRollViewArray.count - 2)) && (self.nextItem == (self.circularRollViewArray.count - 1))){        NSIndexPath *tmpIndexPath = [NSIndexPath indexPathForItem:1 inSection:0];        [self.circularRollView scrollToItemAtIndexPath:tmpIndexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO];    }else{    }    if(indexPath.item == self.circularRollViewArray.count - 1){        self.endDisplayItem = 0;    }else{    }}// 通过这个方法,来控制currentPage- (void)scrollViewDidScroll:(UIScrollView *)scrollView{    NSInteger pageNum = ((scrollView.contentOffset.x + (kscreenWidth / 2.0)) / kscreenWidth);    if (pageNum == 0) {        self.pageControl.currentPage = self.circularRollViewArray.count - 2;    }else if (pageNum > 0 && pageNum < (self.circularRollViewArray.count - 1)){        self.pageControl.currentPage = pageNum - 1;    }else{        self.pageControl.currentPage = 0;    }}//这里是定时器所调用的方法,每调用一次,都向前一张跳转。这里为什么使用self.endDisplayItem而不是使用self.nextItem呢?原因是当你手动拖动的时候,只要稍微拖动一下,就会改变self.nextItem的值,等到定时器下次跳转的时候就会跳转两张,用户体验不是很好。- (void)circularRollViewToNextItem{    NSIndexPath *indexPath = [NSIndexPath indexPathForItem:(self.endDisplayItem + 2) inSection:0];    [self.circularRollView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES];}- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{    [self endTimer];}- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{    [self startTimer];}

大致的核心思想差不多就是那些,下面是一些控件创建的方法

//下面是collectionView的初始化和timer的初始化//这里的_GETTER_BEGIN是自己写的一个宏定义,你们理解就好了。还有一点,当这个view被销毁的时候,一定要记得销毁定时器。_GETTER_BEGIN(UICollectionView, circularRollView){    UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];    flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;    flowLayout.minimumLineSpacing = 0;    flowLayout.itemSize = CGSizeMake(kscreenWidth, (self.CircularRollViewHeight ? self.CircularRollViewHeight : kdefineViewHeight));    _circularRollView = [[UICollectionView alloc] initWithFrame:CGRectMake(0,0,kscreenWidth , kdefineViewHeight) collectionViewLayout:flowLayout];    _circularRollView.showsHorizontalScrollIndicator = NO;    _circularRollView.bounces = NO;    _circularRollView.delegate = self;    _circularRollView.dataSource = self;    _circularRollView.pagingEnabled = YES;    _circularRollView.backgroundColor = kclearColor;    [_circularRollView registerClass:[CirularRollViewCell class] forCellWithReuseIdentifier:NSStringFromClass([CirularRollViewCell class])];}_GETTER_END(circularRollView)_GETTER_BEGIN(NSTimer, timer){    _timer = [NSTimer scheduledTimerWithTimeInterval:3.f target:self selector:@selector(circularRollViewToNextItem) userInfo:nil repeats:YES];    [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];}_GETTER_END(timer)- (void)endTimer{    [self.timer invalidate];    self.timer = nil;}- (void)startTimer{    [self endTimer];    [self timer];}

只视图的搭建这就靠大家自己搭建了,我写的demo里面,pageControl用的就是原生的UIPageControl,不过在外面留一个可以自定义位置的属性。如果大家有什么疑问的地方,可以加我的QQ问我。以后有什么好的方法也会分享给大家。

本论文只是用来学习用的,无限轮播还是有第三方框架的:iCarousel https://github.com/nicklockwood/iCarousel。使用起来也非常的简单

0 0
原创粉丝点击