项目中总有写比较变态的需求,我们的UI设计师有喜欢很酷的交互,其中有个需求类似这种的


右侧部分是可以滚动的当然是无限滚动,这中效果只有UICollectionView的自定义布局才能实现,重写Layout的几个方法主要的代码就是给UICollectionViewLayoutAttributes的属性赋值,主要是为这几个center,size, transform3D;属性赋值,主要使用的是AWCollectionViewDialLayout这个三方的布局。

但是,这个三方并没有实现无限滚动的。无限滚动也可以在scrollViewDidScroll:方法中进行检测,开头和结尾地方多添加几个元素,如果到最后一个了重新回到第一个,但是这种实现有很强的卡顿感,所以后来放弃了这个。后来,在github找到了一种办法,自定义拖拽手势UIPanGestureRecognizer

,然后再拖拽手势的target,action方法中进行判断如果状态来更改UICollectionView的偏移量,代码如下

-(void)customPan:(UIPanGestureRecognizer*)sender{if(sender.state==UIGestureRecognizerStateBegan){self.oldOffset=self.collectionView.contentOffset;}if(sender.state==UIGestureRecognizerStateChanged){CGPointtranslation=[sendertranslationInView:self.collectionView];CGPointoffset;offset.y=(self.oldOffset.y-translation.y);if(fabsf(translation.y)>30){[self.collectionViewsetContentOffset:offsetanimated:NO];}}if(sender.state==UIGestureRecognizerStateEnded){CGPointtranslation=[sendertranslationInView:self.collectionView];self.previousCell=[self.collectionViewcellForItemAtIndexPath:[NSIndexPathindexPathForItem:self.centerIteminSection:0]];NSIntegerstep=1;step=abs(translation.y/item_height)+1;//计算需要走几步if(translation.y>0){////向上滑动if(translation.y>(item_height/2+10)){if((0<self.centerItem)&&(self.centerItem<=(self.count-step))){self.centerItem-=step;}}}elseif(translation.y<0){//向下滑动if(abs(translation.y)>(item_height/2+10)){if((0<=self.centerItem)&&(self.centerItem<self.count-step)){self.centerItem+=step;}}}[self.collectionViewsetContentOffset:CGPointMake(0,self.centerItem*item_height)animated:YES];}}

然后再滚动视图的scrollViewDidEndScrollingAnimation:的代理方法中来判断视图的偏移量如果到首部或者尾部就重新设置UICollectionView的偏移量,这样没有丝毫的卡顿感了,但是却有个很大的缺陷,自定义的手势没有是减速的,最多有个滚动结束时的动画。

UICollectionView的无限滚动的方法我找了很长时间一直没有找到很理想的方法,所以这种只能算是个妥协的方法。