项目中总有写比较变态的需求,我们的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) { CGPoint translation = [sender translationInView:self.collectionView]; CGPoint offset; offset.y = (self.oldOffset.y - translation.y); if (fabsf(translation.y)>30) { [self.collectionView setContentOffset:offset animated:NO]; } } if (sender.state == UIGestureRecognizerStateEnded) { CGPoint translation = [sender translationInView:self.collectionView]; self.previousCell = [self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:self.centerItem inSection:0]]; NSInteger step = 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; } } } else if (translation.y < 0){//向下滑动 if (abs(translation.y)>(item_height/2+10)) { if ((0 <= self.centerItem) && (self.centerItem < self.count - step)) { self.centerItem += step; } } } [self.collectionView setContentOffset:CGPointMake(0, self.centerItem*item_height) animated:YES]; } }
然后再滚动视图的scrollViewDidEndScrollingAnimation:的代理方法中来判断视图的偏移量如果到首部或者尾部就重新设置UICollectionView的偏移量,这样没有丝毫的卡顿感了,但是却有个很大的缺陷,自定义的手势没有是减速的,最多有个滚动结束时的动画。
UICollectionView的无限滚动的方法我找了很长时间一直没有找到很理想的方法,所以这种只能算是个妥协的方法。