ViewController.m
1 // 2 // ViewController.m 3 // IOS_0226_自定义UIColectionView布局 4 // 5 // Created by ma c on 16/2/26. 6 // Copyright © 2016年 博文科技. All rights reserved. 7 // 8 9 #import "ViewController.h" 10 #import "ImgCell.h" 11 #import "LineLayout.h" 12 #import "FoldLayout.h" 13 #import "CircleLayout.h" 14 15 16 @interface ViewController ()<UICollectionViewDataSource,UICollectionViewDelegate> 17 18 @property (nonatomic, strong) NSMutableArray *imgsArray; 19 @property (nonatomic, weak) UICollectionView *collectionView; 20 21 @end 22 23 @implementation ViewController 24 25 static NSString *ID = @"image"; 26 27 - (NSMutableArray *)imgsArray 28 { 29 if (!_imgsArray) { 30 _imgsArray = [NSMutableArray array]; 31 32 for (int i=1; i<9; i++) { 33 [_imgsArray addObject:[NSString stringWithFormat:@"%d.jpg",i]]; 34 35 } 36 } 37 return _imgsArray; 38 } 39 40 - (void)viewDidLoad { 41 [super viewDidLoad]; 42 [self createUI]; 43 } 44 45 - (void)createUI 46 { 47 CGRect rect = CGRectMake(7, 100, 400, 200); 48 UICollectionView *collection = [[UICollectionView alloc] initWithFrame:rect collectionViewLayout:[[FoldLayout alloc] init]]; 49 collection.dataSource = self; 50 collection.delegate = self; 51 // [collection registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:ID]; 52 [collection registerNib:[UINib nibWithNibName:@"ImgCell" bundle:nil] forCellWithReuseIdentifier:ID]; 53 [self.view addSubview:collection]; 54 self.collectionView = collection; 55 56 57 } 58 59 - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event 60 { 61 if ([self.collectionView.collectionViewLayout isKindOfClass:[FoldLayout class]]) { 62 [self.collectionView setCollectionViewLayout:[[CircleLayout alloc] init] animated:YES]; 63 } 64 else{ 65 [self.collectionView setCollectionViewLayout:[[FoldLayout alloc] init] animated:YES]; 66 } 67 } 68 69 #pragma mark - UICollectionViewDataSource 70 71 - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section 72 { 73 return self.imgsArray.count; 74 } 75 76 - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 77 { 78 ImgCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:ID forIndexPath:indexPath]; 79 80 cell.image = self.imgsArray[indexPath.item]; 81 82 return cell; 83 } 84 85 #pragma mark - UICollectionViewDelegate 86 87 - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath 88 { 89 //删除模型数据 90 [self.imgsArray removeObjectAtIndex:indexPath.item]; 91 //刷新UI 92 [collectionView deleteItemsAtIndexPaths:@[indexPath]]; 93 } 94 95 @end
LineLayout.m(线性流水布局)
1 // 2 // LineLayout.m 3 // IOS_0226_自定义UIColectionView布局 4 // 5 // Created by ma c on 16/2/26. 6 // Copyright © 2016年 博文科技. All rights reserved. 7 // 8 9 #import "LineLayout.h" 10 11 static const CGFloat lineLayoutSize = 100; 12 13 @implementation LineLayout 14 15 16 //初始化 17 - (void)prepareLayout 18 { 19 [super prepareLayout]; 20 //设置item大小 21 self.itemSize = CGSizeMake(lineLayoutSize, lineLayoutSize); 22 //设置两端居中 23 CGFloat inset = (self.collectionView.frame.size.width - lineLayoutSize) * 0.5; 24 self.sectionInset = UIEdgeInsetsMake(0, inset, 0, inset); 25 26 //设置水平滚动 27 self.scrollDirection = UICollectionViewScrollDirectionHorizontal; 28 //设置间距 29 self.minimumLineSpacing = lineLayoutSize; 30 31 32 33 //每一个item都有自己的UICollectionViewLayoutAttributes 34 //每一indexPath都有自己的UICollectionViewLayoutAttributes 35 } 36 37 //只要显示的边界发生变化就重新布局:内部会重新调用prepareLayout,layoutAttributesForElementsInRect方法获得所有item的布局属性 38 - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds 39 { 40 return YES; 41 } 42 43 - (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect 44 { 45 //NSLog(@"layoutAttributesForElementsInRect"); 46 // 0.计算可见的矩形框 47 CGRect visibleRect; 48 visibleRect.size = self.collectionView.frame.size; 49 visibleRect.origin = self.collectionView.contentOffset; 50 // 1.获得默认的item的UICollectionViewLayoutAttributes 51 NSArray *array = [super layoutAttributesForElementsInRect:rect]; 52 NSArray * attributes = [[NSArray alloc] initWithArray:array copyItems:YES]; 53 54 55 // 2.计算屏幕最中间的x 56 CGFloat centerX = self.collectionView.contentOffset.x + self.collectionView.frame.size.width * 0.5; 57 58 for (UICollectionViewLayoutAttributes *attr in attributes) { 59 60 if (!CGRectIntersectsRect(visibleRect, attr.frame)) continue; 61 62 // 每一个item中点x 63 CGFloat itemCenterX = attr.center.x; 64 //计算item离屏幕中间的距离 65 CGFloat distance = ABS(itemCenterX - centerX); 66 //距离越小,缩放比例越大 67 CGFloat zoom = 1 - (distance / (self.collectionView.frame.size.width * 0.5)); 68 //NSLog(@"%f",zoom); 69 //缩放比例 70 CGFloat scale = 1 + 0.5 * zoom; 71 //缩放 72 attr.transform3D = CATransform3DMakeScale(scale, scale, 1); 73 } 74 75 return attributes; 76 } 77 78 //用来设置UICollectionView停止滚动那一刻的位置 79 - (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity 80 { 81 // 1.计算UICollectionView最终停止的范围 82 CGRect lastRect; 83 lastRect.origin = proposedContentOffset; 84 lastRect.size = self.collectionView.frame.size; 85 // 计算屏幕中间的x 86 CGFloat centerX = proposedContentOffset.x + self.collectionView.frame.size.width * 0.5; 87 // 2.取出这个范围内的所有属性 88 NSArray *array = [super layoutAttributesForElementsInRect:lastRect]; 89 NSArray * attributes = [[NSArray alloc] initWithArray:array copyItems:YES]; 90 91 92 // 3.遍历所有属性 93 CGFloat adjustOffsetX = MAXFLOAT; 94 for (UICollectionViewLayoutAttributes *attr in attributes) { 95 if (ABS(attr.center.x - centerX) < ABS(adjustOffsetX)) { 96 adjustOffsetX = attr.center.x - centerX; 97 } 98 } 99 return CGPointMake(proposedContentOffset.x + adjustOffsetX, proposedContentOffset.y); 100 } 101 102 @end
FoldLayout.m(折叠布局)
1 // 2 // FoldLayout.m 3 // IOS_0226_自定义UIColectionView布局 4 // 5 // Created by ma c on 16/2/27. 6 // Copyright © 2016年 博文科技. All rights reserved. 7 // 8 9 #import "FoldLayout.h" 10 11 #define Random0_1 (arc4random_uniform(100)/100) 12 13 @implementation FoldLayout 14 15 - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds 16 { 17 return YES; 18 } 19 20 - (CGSize)collectionViewContentSize 21 { 22 return CGSizeMake(500, 500); 23 } 24 25 - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath 26 { 27 NSArray *angles = @[@0, @(-0.2), @(-0.5), @0, @(0.2), @(0.5)]; 28 29 UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; 30 attrs.size = CGSizeMake(100, 100); 31 // attrs.center = CGPointMake(arc4random_uniform(self.collectionView.frame.size.width), arc4random_uniform(self.collectionView.frame.size.height)); 32 attrs.center = CGPointMake(self.collectionView.frame.size.width * 0.5, self.collectionView.frame.size.height * 0.5); 33 if (indexPath.item >= 6) { 34 attrs.hidden = YES; 35 } else { 36 attrs.transform = CGAffineTransformMakeRotation([angles[indexPath.item] floatValue]); 37 //zIndex越大,就越在上面 38 attrs.zIndex = [self.collectionView numberOfItemsInSection:indexPath.section] - indexPath.item; 39 } 40 return attrs; 41 } 42 43 - (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect 44 { 45 NSMutableArray *array = [NSMutableArray array]; 46 NSInteger count = [self.collectionView numberOfItemsInSection:0]; 47 48 for (int i=0; i<count; i++) { 49 // UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:[NSIndexPath indexPathForItem:i inSection:0]]; 50 // attrs.size = CGSizeMake(100, 100); 51 // attrs.center = CGPointMake(self.collectionView.frame.size.width * 0.5, self.collectionView.frame.size.height * 0.5); 52 // if (i >= 5) { 53 // attrs.hidden = YES; 54 // } else { 55 // 56 // NSArray *angles = @[@0, @(-0.2), @(-0.5), @(0.2), @(0.5)]; 57 // attrs.transform = CGAffineTransformMakeRotation([angles[i] floatValue]); 58 // //zIndex越大,就越在上面 59 // attrs.zIndex = count - i; 60 NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0]; 61 UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:indexPath]; 62 [array addObject:attrs]; 63 64 } 65 return array; 66 } 67 68 69 @end
CircleLayout.m(环形布局)
1 // 2 // CircleLayout.m 3 // IOS_0226_自定义UIColectionView布局 4 // 5 // Created by ma c on 16/2/27. 6 // Copyright © 2016年 博文科技. All rights reserved. 7 // 8 9 #import "CircleLayout.h" 10 11 @implementation CircleLayout 12 13 - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds 14 { 15 return YES; 16 } 17 18 - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath 19 { 20 21 UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; 22 attrs.size = CGSizeMake(50, 50); 23 24 //圆的半径 25 CGFloat radius = 70; 26 CGPoint cireclecenter = CGPointMake(self.collectionView.frame.size.width * 0.5, self.collectionView.frame.size.height * 0.5); 27 //每个item间角度 28 CGFloat angleDetla = M_PI * 2 / [self.collectionView numberOfItemsInSection:indexPath.section]; 29 30 //计算当前item角度 31 CGFloat angle = indexPath.item * angleDetla; 32 attrs.center = CGPointMake(cireclecenter.x + radius * cosf(angle), cireclecenter.y + radius * sinf(angle)); 33 34 attrs.zIndex = indexPath.item; 35 return attrs; 36 } 37 38 - (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect 39 { 40 NSMutableArray *array = [NSMutableArray array]; 41 NSInteger count = [self.collectionView numberOfItemsInSection:0]; 42 43 for (int i=0; i<count; i++) { 44 NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0]; 45 UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:indexPath]; 46 [array addObject:attrs]; 47 48 } 49 return array; 50 } 51 52 @end
ImgCell.h(自定义UICollectionViewCell)
1 // 2 // ImgCell.h 3 // IOS_0226_自定义UIColectionView布局 4 // 5 // Created by ma c on 16/2/26. 6 // Copyright © 2016年 博文科技. All rights reserved. 7 // 8 9 #import <UIKit/UIKit.h> 10 11 @interface ImgCell : UICollectionViewCell 12 13 @property (weak, nonatomic) IBOutlet UIImageView *imgView; 14 @property (nonatomic, copy) NSString *image; 15 16 17 @end 18 19 20 // 21 // ImgCell.m 22 // IOS_0226_自定义UIColectionView布局 23 // 24 // Created by ma c on 16/2/26. 25 // Copyright © 2016年 博文科技. All rights reserved. 26 // 27 28 #import "ImgCell.h" 29 30 @interface ImgCell () 31 32 @end 33 34 @implementation ImgCell 35 36 - (void)setImage:(NSString *)image 37 { 38 _image = [image copy]; 39 self.imgView.image = [UIImage imageNamed:_image]; 40 } 41 42 - (void)awakeFromNib { 43 self.imgView.layer.borderWidth = 3; 44 self.imgView.layer.borderColor = [UIColor whiteColor].CGColor; 45 self.imgView.layer.cornerRadius = 5; 46 self.imgView.clipsToBounds = YES; 47 } 48 49 @end