一.子类化UICollectionViewFlowLayout:
代码如下 :
// // LargeCollectionViewLayout.m // Movie 2.0 // // Created by mac1 on 15/10/12. // Copyright (c) 2015年 www.iphonetrain.com. All rights reserved. // #import "LargeCollectionViewLayout.h" #import "Common.h" @implementation LargeCollectionViewLayout - (id)init{ self = [super init]; if (self) { //布局信息 self.itemSize = CGSizeMake(kScreenWidth * 0.75, kScreenHeight - kNavigationBarHeight - kTabBarHeight - kMovieHeaderViewHeight - kMovieFooterViewHeight); //上下分别留出来其他两个部分的位置, //减去距离CollectionView顶部和底部空余的空间 // flowLayout.minimumInteritemSpacing = 0; self.minimumLineSpacing = 0; self.scrollDirection = UICollectionViewScrollDirectionHorizontal; } return self; }
二.设置放大缩小:
//当bounds发生变化时,是否继续布局 - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{ return YES; } //设置一定范围内,CollectionView元素(Cell、装饰视图、补充视图)的布局属性 - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { //先获取rect范围内这些元素,之前的布局信息 NSArray *array = [super layoutAttributesForElementsInRect:rect]; //可见的范围 CGRect visibleRect; visibleRect.origin = self.collectionView.contentOffset; visibleRect.size = self.collectionView.bounds.size; //数组中保存的所有的元素的布局信息 UICollectionViewLayoutAttributes for (UICollectionViewLayoutAttributes *attribute in array) { // NSLog(@"att = %@", attribute); // attribute.transform = CGAffineTransformMakeScale(0.5, 0.5); //判断两个rect是否有交集,如果单元格frame和rect有交叉,修改transform if (CGRectIntersectsRect(attribute.frame, rect)) { // 单元格移动的距离 = 可见范围的中心 - 单元格frame的中心 // CGRectGetMidX(rect)获取rect的中心点的x坐标 CGFloat distance = CGRectGetMidX(visibleRect) - attribute.center.x; CGFloat disScale = distance / 200; if (ABS(distance) < 200) { // ABS(a)取a的绝对值 //放大的比例 CGFloat scale = 1 + 0.1 * (1 - ABS(disScale)); // transform3D 是三维坐标系统的变化 // CATransform3DMakeScale 分别对三个坐标轴进行缩放 // sz参数是第三个坐标轴,垂直于屏幕为坐标轴 attribute.transform3D = CATransform3DMakeScale(scale, scale, 1); // zIndex是z轴方向上的坐标值 attribute.zIndex = 1; } } } //将修改后的布局信息返回 return array; } //返回一个目标偏移量(最终停留的位置) - (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity{ //ProposedContentOffset 如果没有对齐的效果本来应该停留的位置 //找屏幕的中心,取到所有单元格,单元格的中心和屏幕的中心进行比较,找到最接近屏幕中心的单元格 //根据这个单元格,去推算目标偏移量 CGFloat horizontalCenter = (self.collectionView.bounds.size.width / 2) + proposedContentOffset.x; //指定当前显示的范围 CGRect rect = CGRectMake(proposedContentOffset.x, 0, self.collectionView.bounds.size.width, self.collectionView.bounds.size.height); NSArray *array = [super layoutAttributesForElementsInRect:rect]; CGFloat minimumValue = MAXFLOAT; //单元格和屏幕中心差值的最小值 for (UICollectionViewLayoutAttributes *attribute in array) { CGFloat itemCenter = attribute.center.x; if (ABS(itemCenter - horizontalCenter) < ABS(minimumValue)) { minimumValue = itemCenter - horizontalCenter; //最终有一个最接近屏幕中心的单元格 } } //之前偏移量 + (单元格的中心距离当前停留的中心的距离) CGPoint targetContentOffset = CGPointMake(proposedContentOffset.x + minimumValue, proposedContentOffset.y); return targetContentOffset; }