三、让滚轮滑动起来
通过上面的努力,我们已经静态布局出了一个类似pickerView的滚轮,现在我们再来添加滑动滚动的效果
首先,我们需要给collectionView一个滑动的范围,我们以一屏collectionView的滑动距离来当做滚轮滚动一下的参照,我们在布局类中的如下方法中返回滑动区域:
-(CGSize)collectionViewContentSize{
return CGSizeMake(self.collectionView.frame.size.width, self.collectionView.frame.size.height*[self.collectionView numberOfItemsInSection:0]);
}
这时我们的collectionView已经可以进行滑动,但是并不是我们想要的效果,滚轮并没有滚动,而是随着滑动出了屏幕,因此,我们需要在滑动的时候不停的动态布局,将滚轮始终固定在collectionView的中心,先需要在布局类中实现如下方法:
//返回yes,则一有变化就会刷新布局
-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{
return YES;
}
将上面的布局的中心点设置加上一个动态的偏移量:
atti.center = CGPointMake(self.collectionView.frame.size.width/2, self.collectionView.frame.size.height/2+self.collectionView.contentOffset.y);
现在在运行,会发现滚轮会随着滑动始终固定在中间,但是还是不如人意,滚轮并没有转动起来,我们还需要动态的设置每个item的旋转角度,这样连续看起来,滚轮就转了起来,在上面设置布局的方法中,我们在添加一些处理:
//获取当前的偏移量
float offset = self.collectionView.contentOffset.y;
//在角度设置上,添加一个偏移角度
float angleOffset = offset/self.collectionView.frame.size.height;
CGFloat angle = (float)(indexPath.row+angleOffset)/itemCounts*M_PI*2;
再看看效果,没错,就是这么简单,滚轮已经转了起来。
四、让其循环滚动的逻辑
我们再进一步,如果滚动可以循环,这个控件将更加炫酷,添加这样的逻辑也很简单,通过监测scrollView的偏移量,我们可以对齐进行处理,因为collectionView继承于scrollView,我们可以直接在ViewController中实现其代理方法,如下:
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
//小于半屏 则放到最后一屏多半屏
if (scrollView.contentOffset.y<200) {
scrollView.contentOffset = CGPointMake(0, scrollView.contentOffset.y+10*400);
//大于最后一屏多一屏 放回第一屏
}else if(scrollView.contentOffset.y>11*400){
scrollView.contentOffset = CGPointMake(0, scrollView.contentOffset.y-10*400);
}
}
因为咱们的环状布局,上面的逻辑刚好可以无缝对接,但是会有新的问题,一开始运行,滚轮就是出现在最后一个item的位置,而不是第一个,并且有些相关的地方,我们也需要一些适配:
在viewController中:
//一开始将collectionView的偏移量设置为1屏的偏移量
collect.contentOffset = CGPointMake(0, 400);
在layout类中:
//将滚动范围设置为(item总数+2)*每屏高度
-(CGSize)collectionViewContentSize{
return CGSizeMake(self.collectionView.frame.size.width, self.collectionView.frame.size.height*([self.collectionView numberOfItemsInSection:0]+2));
}
//将计算的具体item角度向前递推一个
CGFloat angle = (float)(indexPath.row+angleOffset-1)/itemCounts*M_PI*2;
OK,我们终于大功告成了,可以发现,实现这样一个布局效果炫酷的控件,代码其实并没有多少,相比,数学逻辑要比编写代码本身困难,这十分类似数学中的几何问题,如果你弄清了逻辑,解决是分分钟的事,我们可以通过这样的一个思路,设计更多3D或者平面特效的布局方案,抽奖的转动圆盘,书本的翻页,甚至立体的标签云,UICollectionView都可以实现,这篇博客中的代码在下面的连接中,疏漏之处,欢迎指正!