iOS-UICollectionView
CollectionView:
UICollectionView、UITableView、NSCollectionView
和 UITableView 不同的是,UICollectionView 不局限于垂直的单列布局。相反,collection view有一个 layout 对象,它决定子视图的位置,
先看后面的图片再返回来看比较好理解。
简介:
UICollectionView相对于UITableView很相似,都继承于UIScrollView
UITableView的布局形式比较单一,局限于行列表,
UICollectionView的强大之处在于把视图布局分离出来成为一个独立的类,你想实现怎样的视图布局,就子类化这个类并在其中实现。
UICollectionView默认没有表头, UITableView: 有表头和表尾;
UICollectionView的区里面是项Item, UITableView:区里面是单元格Cell
collectionView和tableView最大的不同之处就是需要自定义cell, collectionView能自动的根据屏幕宽度显示横列竖!
UICollectionView主要用于瀑布流
UICollectionViewLayout是基类,其子类:UICollectionViewFlowLayout,使用的时候都用子类
CollectionView中的每个Item大小和位置可以单独定义
区别:https://blog.csdn.net/vbirdbest/article/details/50720915
必须实现:
1、显示内容完全由layout(布局对象)决定,必须设置UICollectionView的collectionViewLayout
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.minimumLineSpacing = 10;
layout.minimumInteritemSpacing = 20;
UICollectionView *cv = [[UICollectionView alloc]
initWithFrame:CGRectMake(20, 20, 300, 500) collectionViewLayout:layout];
2、必须设置代理
使用UICollectionView的时候,要声明:
1. UICollectionViewDelegateFlowLayout
2. UICollectionViewDataSource,
3. UICollectionViewDelegate
//1中包含了,所以3可以省略
//显示什么内容由数据源决定
//监听由代理决定
3、必须注册cell
[cv registerClass:[UICollectionViewCell class]forCellWithReuseIdentifier:@"ReusableView"];
//ReusableView 这个名字需要和下面4中cellForItemAtIndexPath 定义的一样
4、必须实现 (和UITableview一样) :
cellForItemAtIndexPath //返回cell
numberOfItemsInSection //返回多少行
UICollectionViewFlowLayout
//继承 UICollectionViewLayout
//属性:
minimumLineSpacing //最小行间距
minimumInteritemSpacing //最小内间距(列间距
itemSize
estimatedItemSize
scrollDirection
headerReferenceSize
footerReferenceSize
sectionInset // 段的上下左右的内边距 padding(多个分区一般都会设置该值,如果不设置,多个区会连在一块)
//方法:
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath;
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section;
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section;
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section;
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section;
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section;
UICollectionViewLayout
UICollectionViewLayout的精髓在于你可以定义每个cell的UICollectionViewLayoutAttributes属性
//属性:
frame
center
size
transform3D //可以实现视图的旋转、放大以及透视等效果
bounds
transform
alpha
zIndex
hidden
indexPath
collectionView
//方法:
invalidateLayout
prepareLayout
-(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
UICollectionView
//继承 UIScrollView
//属性
delegate
dataSource
backgroundView
showsHorizontalScrollIndicator
showsVerticalScrollIndicator
.bounces //弹簧效果
//方法
//初始化要设置layout
- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout
//注册cell
- (void)registerClass:(nullable Class)cellClass forCellWithReuseIdentifier:(NSString *)identifier;
//注册头尾
- (void)registerClass:(nullable Class)viewClass forSupplementaryViewOfKind:(NSString *)elementKind withReuseIdentifier:(NSString *)identifier;
- (__kindof UICollectionViewCell *)dequeueReusableCellWithReuseIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath;
- (__kindof UICollectionReusableView *)dequeueReusableSupplementaryViewOfKind:(NSString *)elementKind withReuseIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath;
reloadData
//@required
//每个section有多少Items
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section;
//cell内容
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath;
@optional
//多少Sections
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
//选中后
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
// 取消选中操作
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath
//设置是否允许选中
- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath
// 设置是否允许取消选中
- (BOOL)collectionView:(UICollectionView *)collectionView shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath
//动态设置每个Item的尺寸大小
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath;
//动态设置每个分区的EdgeInsets
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section;
//动态设置每行的间距大小
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section;
//动态设置每列的间距大小
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section;
//动态设置某组头视图大小
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section;
//动态设置某组尾视图大小
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section;
//设置段头段位
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath{
//下面这两个方法,可以重新设置collection的布局,后面的方法多了一个布局完成后的回调,iOS7后可以用
//使用这两个方法可以产生非常炫酷的动画效果
- (void)setCollectionViewLayout:(UICollectionViewLayout *)layout animated:(BOOL)animated;
- (void)setCollectionViewLayout:(UICollectionViewLayout *)layout animated:(BOOL)animated completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);
//下面这些方法用于动态添加,删除,移动某些分区获取items
- (void)insertSections:(NSIndexSet *)sections;
- (void)deleteSections:(NSIndexSet *)sections;
- (void)reloadSections:(NSIndexSet *)sections;
- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection;
- (void)insertItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths;
- (void)deleteItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths;
- (void)reloadItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths;
- (void)moveItemAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath;
UICollectionViewCell
//继承 UICollectionReusableView :UIView
//属性:
contentView
selected
highlighted
backgroundView
selectedBackgroundView
//方法:
代码 实例:
static NSString *const cellId = @"ReusableView";
static NSString *const headerId = @"ReusableHeaderView";
static NSString *const footerId = @"ReusableFooterView";
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.view.backgroundColor = [UIColor orangeColor];
//UICollectionViewLayout *layout = [[UICollectionViewLayout alloc] init];
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.minimumLineSpacing = 10;
layout.minimumInteritemSpacing = 20;
layout.itemSize = CGSizeMake(50, 50);
layout.headerReferenceSize = CGSizeMake(300, 50);
layout.footerReferenceSize = CGSizeMake(300, 50);
layout.sectionInset = UIEdgeInsetsMake(10, 10, 0, 10);
layout.scrollDirection = UICollectionViewScrollDirectionVertical;
UICollectionView *cv = [[UICollectionView alloc] initWithFrame:CGRectMake(20, 20, 300, 500) collectionViewLayout:layout];
cv.backgroundColor = [UIColor blackColor];
cv.delegate = self;
cv.dataSource = self;
[cv registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"ReusableView"];
[cv registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"ReusableHeaderView"];
[cv registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"ReusableFooterView"];
//[cv registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"ReusableView"];
[self.view addSubview:cv];
}
- (nonnull __kindof UICollectionViewCell *)collectionView:(nonnull UICollectionView *)collectionView cellForItemAtIndexPath:(nonnull NSIndexPath *)indexPath {
NSString *cvCell = @"ReusableView";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cvCell forIndexPath:indexPath];
//UICollectionViewCell * cell = [[UICollectionViewCell alloc]init]; 这样崩溃,必须如上复用。也不用对cell进行空值判断 if(!cell){}
//CollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cvCell forIndexPath:indexPath];
[cell sizeToFit];
UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"%ld",indexPath.row]];
UIImageView *imageV = [[UIImageView alloc] initWithImage:image];
imageV.frame = CGRectMake(0, 0, 30, 30);
[cell.contentView addSubview:imageV];
if (indexPath.section % 2 == 0) {
cell.backgroundColor = [UIColor whiteColor];
}else{
cell.backgroundColor = [UIColor redColor];
}
return cell;
}
- (NSInteger)collectionView:(nonnull UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 10;
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
return 2 ;
}
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
if (indexPath.row%2 == 0) {
return CGSizeMake(60, 80);
}else{
return CGSizeMake(80, 60);
}
return CGSizeMake(60, 80);
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
NSLog(@"click cell");
}
//footer的size
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section
{
return CGSizeMake(10, 10);
}
//header的size
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
{
return CGSizeMake(10, 10);
}
//设置每个item的UIEdgeInsets
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(10, 10, 10, 10);
}
//设置每个item水平间距
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
{
return 10;
}
//设置每个item垂直间距
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
return 15;
}
// 和UITableView类似,UICollectionView也可设置段头段尾
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath{
if([kind isEqualToString:UICollectionElementKindSectionHeader]){
UICollectionReusableView * headerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"ReusableView" forIndexPath:indexPath];
UIView * contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 50)];
contentView.backgroundColor = [UIColor grayColor];
UILabel * label = [[UILabel alloc] initWithFrame:CGRectMake(20, 10, self.view.frame.size.width, 30)];
label.text = [NSString stringWithFormat:@"Section Header: %ld", indexPath.section];
label.textAlignment = NSTextAlignmentCenter;
[contentView addSubview:label];
[headerView addSubview:contentView];
return headerView;
}
else if([kind isEqualToString:UICollectionElementKindSectionFooter]){
}
return nil;
}
- (BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath*)destinationIndexPath
{
}
区别.png
垂直水平排列.png
1648725-81eb0f19e60dbaeb.jpg
屏幕快照 2018-05-28 13.48.22.png
在实际开发过程中,很可能行间距会是不同的.png
问题:
1、cell 重叠 ?
自定义UICollectionViewCell
参考:
https://blog.csdn.net/lvxiangan/article/details/73826108 超全
https://blog.csdn.net/eqera/article/details/8134986
https://www.jianshu.com/p/cf616f73d596 实践