利用UICollectionView实现电影轮播图效果
2016-09-07 本文已影响320人
静谧无际
在开发项目的过程中,有一个类似电影轮播效果的需求,最中间图片正常显示,两侧的图片随着偏移量的改变而缩小,并且具有pageEnable的效果,最初在github上找到类似的一个控件,该控件是对scrollView进行的自定制,虽然可以实现想要的效果但是内存消耗的大多,生成了许多多余的视图,最后决定自己定制该效果的视图。
目的效果
![](https://img.haomeiwen.com/i2286896/982aca7fb36afa81.png)
效果分析
- 图片需要随偏移量的改变而缩小,可以自定义UICollectionViewFlowLayout来实现该效果。
- 控件需要实现pageable的效果,但需要自定义,pageable移动的距离。
- 要注意内存的使用,要实现视图重用。
经过分析,继承UICollectionView来实现目的效果。
实现过程
- 解决pageable的移动距离
-(void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset{
self.velocity = velocity;
self.endPoint = scrollView.contentOffset;
self.direction = self.startPoint.x <= self.endPoint.x ? FlowDirectionRight : FlowDirectionLeft;
CGFloat x = targetContentOffset->x;
CGFloat y = targetContentOffset->y;
self.targetPoint = CGPointMake(x, y);
NSInteger currentPage = [self currentPageWithScrollView:scrollView];
CGFloat overOffsetX = scrollView.contentOffset.x - currentPage* self.pageLength - self.itemLength/2;//滑动到最左端时进行定位
if(overOffsetX < 0){
targetContentOffset->x = self.contentOffset.x;
[scrollView setContentOffset:CGPointMake(self.itemLength/2, 0) animated:YES];
self.currentPage = 0;
return;
}//滑动最右端是进行定位
CGFloat maxOffsetX = (self.contentSize.width - self.frame.size.width - self.itemLength/2);
if(self.contentOffset.x > maxOffsetX){
targetContentOffset->x = self.contentOffset.x;
[scrollView setContentOffset:CGPointMake(maxOffsetX, 0) animated:YES];
self.currentPage = self.itemImages.count-3;
return;
}//当向右滑动时
if(self.direction == FlowDirectionRight){
if(overOffsetX >= self.pageLength/7){
targetContentOffset->x = (currentPage+1)*self.pageLength+self.itemLength/2;
self.currentPage = currentPage+1;
}else{
self.currentPage = currentPage;
if(self.velocity.x == 0){
targetContentOffset->x = (currentPage)*self.pageLength+self.itemLength/2;
}else{
targetContentOffset->x = scrollView.contentOffset.x;
[scrollView setContentOffset:CGPointMake((currentPage)*self.pageLength+self.itemLength/2, 0) animated:YES];
}
}
}//当向左滑动时
else{
if(overOffsetX >= self.pageLength/7*6){
self.currentPage = currentPage+1;
if(self.velocity.x == 0){
targetContentOffset->x = (currentPage+1)*self.pageLength+self.itemLength/2;
}else{
targetContentOffset->x = scrollView.contentOffset.x;
[scrollView setContentOffset:CGPointMake((currentPage+1)*self.pageLength+self.itemLength/2, 0) animated:YES];
}
}else{
self.currentPage = currentPage;
targetContentOffset->x = (currentPage)*self.pageLength+self.itemLength/2;
}
}
}
}
实现自定义pageable的距离的关键是改变参数targetContentOffset的值,由于传过来的是指针,可以对值直接进行修改,来达到滑动自定义距离的目的
- 解决视图的缩放问题
自定义UICollectionViewFlowLayout
重写-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect方法。
-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect
{
NSArray *array = [super layoutAttributesForElementsInRect:rect];//可见frame
CGRect visibleRect;
visibleRect.origin = self.collectionView.contentOffset;
visibleRect.size = self.collectionView.frame.size;
NSMutableArray *allAttributes = [NSMutableArray arrayWithCapacity:array.count];
for(UICollectionViewLayoutAttributes *attributes in array)
{
UICollectionViewLayoutAttributes *newAttributes = [attributes copy];
[allAttributes addObject:newAttributes];
if(CGRectIntersectsRect(newAttributes.frame, visibleRect))
{
CGFloat distance = CGRectGetMidX(visibleRect) - newAttributes.center.x;
CGFloat scale = ABS(distance)/(self.collectionView.frame.size.width/2);
CGFloat adverseScale = ABS(1-scale);
CGFloat trueScale = (1-self.sizeScale)*adverseScale + self.sizeScale;
newAttributes.transform3D = CATransform3DMakeScale(trueScale, trueScale, 1.0);
newAttributes.zIndex = 1;
}
}
return allAttributes;
}
最终实现效果
![](https://img.haomeiwen.com/i2286896/53042c3a011c80fb.gif)
具体代码前往Github下载
如有疑问请发邮件欢迎骚扰😀
GitHub地址:@https://github.com/somson/flowView
邮箱地址:1246071387@qq.com