效果图
一.我们要对UICollectionView的布局进行自定义
这是我自定义的宏以及静态变量
#define WIDTH [UIScreen mainScreen].bounds.size.width #define Height [UIScreen mainScreen].bounds.size.height #define CWColor(a,b,c) [UIColor colorWithRed:(a)/255.0 green:(b)/255.0 blue:(c)/255.0 alpha:1.0] /** * static 表示只在此文件里可以访问(防止其他文件访问) const防止别人去改 */ static NSString *const ID = @"cellID";
- 1.自定义布局,集成
UICollectionViewFlowLayout
即可布局的设置(重点)UICollectionViewFlowLayout
继承它就拥有流水的效果UICollectionViewLayout
如果继承它,那么一切布局要从头开始下面我们就重点讲讲自定义布局的里面一些知识点,我就以我布局的CWLineLayout为例
#import "CwLineLayout.h" #define WIDTH [UIScreen mainScreen].bounds.size.width #define Height [UIScreen mainScreen].bounds.size.height static const CGFloat CWItemH = 120; @implementation CwLineLayout -(instancetype)init { self = [super init]; if (self) { } return self; } /** * 此方法可在collectionView之后进行走的 */ -(void)prepareLayout { //设置格子的大小 self.itemSize = CGSizeMake(CWItemH, CWItemH); CGFloat inset = (self.collectionView.frame.size.width-CWItemH)*0.5; self.sectionInset = UIEdgeInsetsMake(0, inset, 0, inset); self.minimumLineSpacing = 100; /** * 设置滑动方向 * UICollectionViewScrollDirectionHorizontal 水平方向 * UICollectionViewScrollDirectionVertical 垂直方向 */ self.scrollDirection = UICollectionViewScrollDirectionHorizontal; /* // //设置最小行间距 // self.minimumLineSpacing = 10; // // //设置最小列间距 // self.minimumInteritemSpacing = 10; // // //设置与四周的边距 // self.sectionInset = UIEdgeInsetsMake(5, 5, 5, 5); */ /** * 每一个cell(item)都有自己的UICollectionViewLayoutAttributes * 每一个indexPath都有自己的UICollectionViewLayoutAttributes */ } /** * 用来设置collectionView停止滚动那一刻的位置 * * @param proposedContentOffset collectionView原本停留的位置 * @param velocity 滚动的速度 */ -(CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity { //1.计算scrollview最后会停留的范围 CGRect lastRect; lastRect.origin = proposedContentOffset; lastRect.size = self.collectionView.frame.size; //计算屏幕最中间的x CGFloat centerX = proposedContentOffset.x + self.collectionView.frame.size.width*0.5; //2.取出这个范围内的所有属性 NSArray *array1 = [self layoutAttributesForElementsInRect:lastRect]; //遍历所有的属性 CGFloat adjustOffsetX = MAXFLOAT; for (UICollectionViewLayoutAttributes *array2 in array1) { if (ABS(array2.center.x - centerX) < ABS(adjustOffsetX)) { adjustOffsetX = array2.center.x - centerX; } } return CGPointMake(proposedContentOffset.x+adjustOffsetX, proposedContentOffset.y); } /** * 对collection的滚动进行实时监控 * 只要显示的便捷发生改变就进行重新布局,内部会重新调用 layoutAttributesForElementsInRect:(CGRect)rect,获得所有cell的布局属性 */ -(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { return YES; } /** * 对传进来的item进行监听 */ -(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect { //计算呢可见的矩形框 CGRect visiableRect; visiableRect.size = self.collectionView.frame.size; visiableRect.origin = self.collectionView.contentOffset; //1.取出默认的cell的 UICollectionViewLayoutAttributes,super是返回所有的图片 NSArray *array = [super layoutAttributesForElementsInRect:rect]; //计算屏幕最中间的x CGFloat centerX = self.collectionView.contentOffset.x + self.collectionView.frame.size.width*0.5; //2.遍历所有的布局属性 for (UICollectionViewLayoutAttributes *attributes in array) { if (!CGRectIntersectsRect(visiableRect, attributes.frame)) { continue; } //每一个item中点的x CGFloat itemCenterX = attributes.center.x; //根据屏幕最中间的距离计算缩放比例,差距越小缩放比例越大 CGFloat scale = 1+ 1 - ABS(itemCenterX - centerX)/(self.collectionView.frame.size.width*0.5); attributes.transform3D = CATransform3DMakeScale(scale, scale, scale); } return array; } @end
- 2.建立
UICollectionView
(挂代理,遵守协议)
<UICollectionViewDataSource,UICollectionViewDelegate>
/** * UICollectionView的创建 */ UICollectionView *collectionView = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 100, WIDTH, WIDTH) collectionViewLayout:layout]; collectionView.backgroundColor = CWColor(255, 255, 0); collectionView.showsHorizontalScrollIndicator = NO; collectionView.delegate = self; collectionView.dataSource = self; /** * 注册UICollectionView */ [collectionView registerNib:[UINib nibWithNibName:@"CWImageCell" bundle:nil] forCellWithReuseIdentifier:ID]; [self.view addSubview: collectionView];
3.CollectionView的代理方法
#pragma mark collectionView的代理方法的实现 -(NSInteger )collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return self.imageArray.count; } -(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { CWImageCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:ID forIndexPath:indexPath]; cell.imageName = self.imageArray[indexPath.item]; cell.number.text = [NSString stringWithFormat:@"%ld",(long)indexPath.item+1]; return cell; } /** * collectionView的点击事件 */ -(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { //删除模型数据(删除的指定item) [self.imageArray removeObjectAtIndex:indexPath.item]; //刷新UI [collectionView deleteItemsAtIndexPaths:@[indexPath]]; } -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { /** * 动画式切换 */ if ([self.collectionView.collectionViewLayout isKindOfClass:[CwLineLayout class]]) { [self.collectionView setCollectionViewLayout:[[UICollectionViewFlowLayout alloc]init] animated:YES]; }else { [self.collectionView setCollectionViewLayout:[[CwLineLayout alloc]init] animated:YES]; } } #pragma mark 图片数组化 -(NSMutableArray *)imageArray { if (!_imageArray) { _imageArray = [[NSMutableArray alloc]init]; for (int i = 1; i <= 13 ; i++) { [_imageArray addObject:[NSString stringWithFormat:@"%d.jpg",i]]; } } return _imageArray; }
简单的相册demo 密码: fm69
实例2旋转相册 密码:hwh3
值得注意的是layout的一个属性
// zIndex越大,就越在上面 attrs.zIndex = [self.collectionView numberOfItemsInSection:indexPath.section] - indexPath.item;
实例3.圆形角度相册 密码: yj7w
大总结:在进行layout 进行布局时记住如下几点:
- 1.继承方式
UICollectionViewFlowLayout 继承它就拥有流水的效果
UICollectionViewLayout 如果继承它,那么一切布局要从头开始 - 2.在第二种继承方式里面layout重新布局的类.m中不可缺少的方法(一般来说这3个方法不可缺少)
/** * 对collection的滚动进行实时监控 * 只要显示的便捷发生改变就进行重新布局,内部会重新调用 layoutAttributesForElementsInRect:(CGRect)rect,获得所有cell的布局属性 */ -(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { return YES; } /** * 位置改变就重新布局 */ -(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect { NSMutableArray *array = [NSMutableArray array]; NSInteger count = [self.collectionView numberOfItemsInSection:0]; for (int i = 0; i < count; i++) { UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]]; [array addObject:attrs]; } return array; } //在此里面进行自己想要的设置 -(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; attrs.size = CGSizeMake(50,50); attrs.zIndex = indexPath.item; return attrs; }
提示: UICollectionView 滚动条去掉
垂直滚动条 XXX.showsVerticalScrollIndicator = NO; 水平滚动条 XXX.showsHorizontalScrollIndicator = NO;