在很多app中都有这样通用的页面,一直没有机会使用UICollectionView
,只是简单的看过他的使用方法。今天公司美工出图,使用了他,并且遇到了好多的坑。记录一下过程,不确定使用的方法是不是最优的,如果有更好的方案,一起讨论,一起进步
理论篇
一.UICollectionViewLayout是做什么的?
1.1 在创建UITableView
的时候,使用的是- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style
用于判断是普通还是分组,
1.2 UICollectionViewLayout
实际的作用是一样的,是用来设置cell的布局的,初始化collectionView
的时候,一定要给他设置这个属性,否者不会显示。UICollectionViewFlowLayout
是UICollectionViewLayout
的子类,给collectionView赋值的时候,一定要使用 UICollectionViewFlowLayout初始化。
1.3 UICollectionViewFlowLayout
和UICollectionViewLayout
的关系就像是UIGestureRecognizer
和UITapGestureRecognizer
的一样。一个是父类,一个是子类。使用的时候都用子类
二. UICollectionViewLayout的属性
如果都是固定的,建议生成layout对象的时候,设置全局属性,(其布局很有意思,当你的cell设置大小后,一行多少个cell,由cell的宽度决定)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
NS_CLASS_AVAILABLE_IOS(6_0) @interface UICollectionViewFlowLayout : UICollectionViewLayout //每行之间竖直之间的最小间距 (可以大于) @property (nonatomic) CGFloat minimumLineSpacing; //同行的cell与cell之间水平之间的最小间距(可以) @property (nonatomic) CGFloat minimumInteritemSpacing; //每个cell的尺寸,如果都是上图的那种,整个collectionView都是同一种,那么可以用整个属性,如果想我们公司那样的样式,不建议设置该属性 @property (nonatomic) CGSize itemSize; //预估cell的尺寸,ios8之后可以先去预估cell的尺寸,然后去自适应 @property (nonatomic) CGSize estimatedItemSize NS_AVAILABLE_IOS(8_0); // defaults to CGSizeZero - setting a non-zero size enables cells that self-size via -perferredLayoutAttributesFittingAttributes: //滑动的方向,水平或者竖直,看到很多图片浏览器都是用collectionview做出来的(注册之后,可以复用),非常的好用!但是要记住,水平滑动只有collectionview有,tableview不支持的,默认竖直方法滑动 @property (nonatomic) UICollectionViewScrollDirection scrollDirection; // default is UICollectionViewScrollDirectionVertical //组头组尾的size @property (nonatomic) CGSize headerReferenceSize; @property (nonatomic) CGSize footerReferenceSize; //组的四周切的范围 @property (nonatomic) UIEdgeInsets sectionInset; @end |
minimumLineSpacing 属性详解
sectionInset 属性详解
注意,我刚才说的,如果所有的cell都是一样尺寸,我们可以设置初始化layout之后,直接赋值,如果想我们公司那样,随意可能改变,建议看看下边的代理方法
三. UICollectionViewLayout的代理方法
3.1 过去我们使用UITableView
的时候,直接声明数据源方法,和代理方法,
3.2 使用UICollectionView
的时候,也要声明两个。
1.UICollectionViewDelegateFlowLayout
2.UICollectionViewDataSource
,
因为1中包含了3.UICollectionViewDelegate
,所以可以省略3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
#pragma mark - UICollectionViewDelegateFlowLayout //每个cell的大小,因为有indexPath,所以可以判断哪一组,或者哪一个item,可一个给特定的大小,等同于layout的itemSize属性 - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { return CGSizeMake(34,56); } // 设置整个组的缩进量是多少 - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { return UIEdgeInsetsMake(5, 5, 5, 5); } // 设置最小行间距,也就是前一行与后一行的中间最小间隔 - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section { return 10; } // 设置最小列间距,也就是左行与右一行的中间最小间隔 - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section { return 10; } // 设置section头视图的参考大小,与tableheaderview类似 - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section { return CGSizeMake(self.view.frame.size.width, 40); } // 设置section尾视图的参考大小,与tablefooterview类似 - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section { return CGSizeMake(self.view.frame.size.width, 40); } |
四. UICollectionView的组头和组尾(页眉和页脚)
1.
UICollectionView
中非常明确是以组为单位,可以设置组的组头和尾巴,这里的头尾还可以复用
2.复用的时候,首先头尾view要继承于
UICollectionReusableView
,然后注册(分为nib和class两种)
3.用的时候通过collectionView去dequeue一下获取,和cell的思路一样
4.可以使用上文中的layout属性直接设置组头和组尾的size,也可以使用代理方法,去设置
五. UICollectionView的数据源方法
和tableview的数据源方法一样,想要成为其数据源,然后声明数据源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#pragma mark - UICollectionViewDataSource // 指定Section个数 - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { return 3; } // 指定section中的collectionViewCell的个数 - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return 10; } // 配置section中的collectionViewCell的显示 - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { CollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"CellIdentifier" forIndexPath:indexPath]; cell.backgroundColor = [UIColor redColor]; cell.textLabel.text = [NSString stringWithFormat:@"(%ld %ld)", indexPath.section, indexPath.row]; return cell; } |
六. UICollectionView的代理方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
#pragma mark - UICollectionViewDelegate // 允许选中时,高亮 - (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath { NSLog(@"%s", __FUNCTION__); return YES; } // 高亮完成后回调 - (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath { NSLog(@"%s", __FUNCTION__); } // 由高亮转成非高亮完成时的回调 - (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath { NSLog(@"%s", __FUNCTION__); } // 设置是否允许选中 - (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath { NSLog(@"%s", __FUNCTION__); return YES; } // 设置是否允许取消选中 - (BOOL)collectionView:(UICollectionView *)collectionView shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath { NSLog(@"%s", __FUNCTION__); return YES; } // 选中操作 - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { NSLog(@"%s", __FUNCTION__); } // 取消选中操作 - (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *) |