1.最简单的UICollectionView
UICollectionView是一个使用起来比较复杂的视图,即使是最简单的实现,也必须提供数据源dataSource,和布局方法UICollectionViewLayout,才可以实现一个可见可用的视图效果。
与TableView相同,dataSource需要提供的是
- collectionView:numberOfItemsInSection: //返回每段显示的数据个数
- collectionView:cellForItemAtIndexPath: // 返回数据的显示cell获取cell必须使用dequeueReusableCellWithReuseIdentifier:forIndexPath:方法,与TableView不同的是,这里不会返回nil,而是必须把cell的类别注册到collectionView供此方法调用,否则会出错。
布局我们使用已经提供的UICollectionViewLayout的子类UICollectionViewFlowLayout,在初始化UICollectionView的时候传入
UICollectionViewFlowLayout *layout = [UICollectionViewFlowLayout new];
UICollectionView *collectionView = [[UICollectionView alloc]initWithFrame:self.view.bounds collectionViewLayout:layout];
collectionView.dataSource = self;
layout.itemSize = CGSizeMake(50, 50); //设定大小
2.UICollectionViewCell详解
UICollectionViewCell不像UITableViewCell一样提供了可用的几种样式,因此建议实现其子类来使用。 子类实现时候的几个注意点:
所有的自定义View需要加入contentView中。
实现prepareForReuse对重用cell进行必要的清理。
定义selectedBackgroundView来实现选中时候的区分背景
使用前先需要先注册:
[collectionView registerClass:[CustomCollectionViewCell class] forCellWithReuseIdentifier:@“MyIdentifier”];
对于段头或者段尾等附加显示的元素,同样需要注册:
[collectionView registerClass:[CustomCollectionViewCell class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader(Footer) withReuseIdentifier:@“HeaderIdentifier"];
并提供相应的dataSource方法:
collectionView:viewForSupplementaryElementOfKind:atIndexPath:
别忘了还需要设置layout:
对于UICollectionViewFlowLayout来说,可以使用
head(foot)erReferenceSize
或者代理方法:- collectionView:layout:referenceSizeForHead(Foot)erInSection:
cell和SupplementaryView的indexPath是分别计数的,互不干扰。SupplementaryView中的Header和Footer计数也是分开的,尽管他们需要在同一个数据方法里面实现。
3.UICollectionView的选择
UICollectionView选择的delegate方法跟UITableView的选择基本一致,这里就不详细说了,比较简单。 略有不同的是,UICollectionView没有默认highlighted的颜色样式,需要自己通过代理方法设置,cell里面是选中的颜色,而不是highlighted的颜色,区别应当注意。
4.UICollectionView的插入删除和移动
与TableView不同,UICollectionView没有默认的删除和插入,也没有代理方法,而是直接调用其类方法即可
- insertItemsAtIndexPaths: //插入
moveItemAtIndexPath:toIndexPath: //移动
deleteItemsAtIndexPaths: //删除
同样可以进行批量操作。
- performBatchUpdates:completion:
5.cell的拷贝和粘贴或者自定义操作
长按cell的时候出现可以出现菜单,这个菜单是由UIMenuController实现的,它包含了剪切、拷贝、粘贴、删除等等操作,要实现这个菜单,必须实现三个方法
collectionView:shouldShowMenuForItemAtIndexPath: //是否弹出菜单,需要返回YES
- collectionView:canPerformAction:forItemAtIndexPath:withSender: //是否可以弹出事件
假如我们只想使用拷贝和粘贴,可以这样写:
- (BOOL)collectionView:(UICollectionView *)collectionView
canPerformAction:(SEL)action
forItemAtIndexPath:(NSIndexPath *)indexPath
withSender:(id)sender {
if ([NSStringFromSelector(action) isEqualToString:@"copy:"]
|| [NSStringFromSelector(action) isEqualToString:@"paste:"])
return YES;
return NO;
}
- collectionView:performAction:forItemAtIndexPath:withSender: //对事件进行相应操作
6.自定义布局
当UICollectionViewFlowLayout以及其子类不能满足布局的需求时,可以创造UICollectionViewLayout的子类进行自动布局。
简单来讲,自定义布局就是需要提供所有元素的位置,随后,collectionView:cellForItemAtIndexPath等方法会根据layout来请求元素。
自定义自动布局必须需要重写的方法有:
-collectionViewContentSize
返回collectionView的大小
-layoutAttributesForElementsInRect:
返回区域内元素的属性数组
-layoutAttributesForItemAtIndexPath:
返回cell的布局属性
-layoutAttributesForSupplementaryViewOfKind:atIndexPath:
返回SupplementaryView的布局属性(可选)
-layoutAttributesForDecorationViewOfKind:atIndexPath:
返回DecorationView的布局属性(可选)
-shouldInvalidateLayoutForBoundsChange:
边界变化时是否自动布局,返回BOOL
建议写法:
首先实现方法
- (void)prepareLayout {
此方法中计算出全部元素布局所需要的属性并以indexPath为关键字存入字典
cell属性的生成方法:
UICollectionViewLayoutAttributes *attr = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
SupplementaryView属性的生成方法:
UICollectionViewLayoutAttributes *attr = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:@"customId" withIndexPath:indexPath];
根据indexPath确定attr的frame,或者使用center和size属性来确定frame。
把attr保存到字典中
}
- (CGSize)collectionViewContentSize {
通过self.collectionView获取相关信息并计算大小
}
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
建立一个可变数组attributes
遍历所有存储的attr
如果frame存在于rect中,则加入数组
if(CGRectIntersectsRect(rect, attr.frame)){
[attributes addObject:attr];
}
返回数组
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
只需要返回存储字典里的独立属性即可。
}