iOS-UICollectionView

2018-04-05  本文已影响30人  我是谁重要吗

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 实践

https://blog.csdn.net/vbirdbest/article/details/50720915 有图

上一篇下一篇

猜你喜欢

热点阅读