爬爬爬之路:UI(十八) 集合视图(UICollectionView)

来源:互联网 发布:讨论网络协议的优缺点 编辑:程序博客网 时间:2024/05/21 03:18

UICollectionView

集合视图和TalbeView有许多相似之处, 和TableView不同的是, TableVIew是以行为单位, 每行拥有一个TableViewCell, 而集合视图是一一个item作为单位, 一行可以有多个item. 而每个Item的大小也可以不同, 通常需要自己重新定制.

集合视图和TableView相同的是, 可以设置分区数, 可以设置每个分区下的成员个数. 可以给每个分区设置表头 和表尾

和TableView不同, CollectionView需要一个布局格式类(UICollectionViewLayout)来设置CollectionView的界面框架布局.

在框架样式上, CollectionView比TableView要更加复杂.

关键属性

@property (nonatomic, retain) UICollectionViewLayout *collectionViewLayout;@property (nonatomic, assign) id <UICollectionViewDelegate> delegate;@property (nonatomic, assign) id <UICollectionViewDataSource> dataSource;

其中collectionViewLayout是用于控制集合视图的框架布局.
delegate是响应集合视图的手势交互操作的代理对象
dataSource是控制集合视图具体内容的代理代理对象


UICollectionViewFlowLayout类

UICollectionViewLayout是一个抽象类, 具体功能是有它的子类实现.
UICollectionViewFlowLayout是系统提供的一个UICollectionViewLayout的子类 可实现网状结构的布局.

一般情况下, 用UICollectionViewFlowLayout即可应对需求.

布局相关的属性

  1. 控制行与行之间的最小间距
    @property (nonatomic) CGFloat minimumLineSpacing;
  2. 控制列与列之间的最小间距
    @property (nonatomic) CGFloat minimumInteritemSpacing;
  3. 设置每个item的大小
    @property (nonatomic) CGSize itemSize;
  4. 限制item的大小
    @property (nonatomic) CGSize estimatedItemSize;
  5. 设置集合视图滚动的方向
    @property (nonatomic) UICollectionViewScrollDirection scrollDirection;
    分为横向UICollectionViewScrollDirectionHorizontal
    和纵向UICollectionViewScrollDirectionVertical 两种
    默认是纵向的.
  6. 设置表头的大小
    @property (nonatomic) CGSize headerReferenceSize;
    注意, 表头大小的宽度和高度是受集合视图滚动方向影响的.
    当集合视图的滚动方向为纵向的时候, 表头的宽度设置不会影响表头的实际显示宽度
    当集合视图的滚动方向是横向的时候, 表头的高度设置不会影响表头的实际显示高度
  7. 设置表尾的大小
    @property (nonatomic) CGSize footerReferenceSize;
    设置限制同表头
  8. 设置分区内边距
    @property (nonatomic) UIEdgeInsets sectionInset;
    返回值的结构如下

    typedef struct UIEdgeInsets {    CGFloat top, left, bottom, right;} UIEdgeInsets;

    作用是设置一个分区内的所有处于边缘的item 距离对应方向的边缘的距离.
    创建方法如下

    UIEdgeInsets UIEdgeInsetsMake(CGFloat top, CGFloat left, CGFloat bottom, CGFloat right) {    UIEdgeInsets insets = {top, left, bottom, right};    return insets;}

UICollectionViewDelegate协议

常用方法如下:

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath;

响应某个item的点击时间, item的索引indexPath和TableView中的indexPath相同.

另外的, UICollectionViewFlowLayout类中也给UICollectionViewDelegate延展了一些新的协议方法

主要内容如下:

@protocol UICollectionViewDelegateFlowLayout <UICollectionViewDelegate>@optional// 设置某个item的大小, 若已用属性itemSize设置过, 依然已此方法为准, 下同- (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;@end

UICollectionViewDataSource协议

必须重写的方法

// 某个分区下item的个数, 若没有设置分区个数, 默认为1- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section;// 设置某个item的具体样式, 具体样式可以自定义一个UICollectionViewCell的子类来实现- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath;

和TableViewCell相似, UICollectionViewCell也有重用机制. 但是两者在书写上略有不同.
UICollectionViewCell需要事先注册, 并给定标识符. 在cellForItemAtIndexPath方法中必须使用
-dequeueReusableCellWithReuseIdentifier:forIndexPath:
方法获取重用池中的cell. 同时本方法的作用还有若是没有获取到cell会自动创建一个cell. 且自动创建cell的时候会触发cell的initWithFrame:方法

注册语句如下:

// 若是需要用到自定义cell, 就填写自定义cell的类名, 注意注册的标识符和取出重用标识符一致.// 若是需要用到多个自定义cell, 则需要执行多个注册语句. 注意标识符不能重复.[collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cell"];
// 从重用池中取出cellUICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];// 可以利用indexPath判断当前需要取出的cell是哪个类的cell. 注意此处出现的标识符必须是已经注册过的标识符, 且标识符和cell所属的类必须对应.

可选择重写方法

// 设置分区数的方法- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView;// 设置表头和表尾样式的方法, 通过kind属性来判断当前是表头还是表尾- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath;// kind值分为两种: // UICollectionElementKindSectionHeader 和 UICollectionElementKindSectionFooter// 前者表示表头, 后者表示表尾

表头表尾同样有重用机制. 和cell一样, 也需要先进行注册以后才能使用
表头表尾是属于UICollectionReusableView(可重用视图类)或其子类的对象
系统自身的表头表尾是什么都没有的, 若需要添加表头表尾需要自己自定义UICollectionReusableView的子类.
若要显示表头表尾, 必须要给定一个表头表尾的大小.

// 注册表头[collectionView registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"header"];// 注册表尾[collectionView registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"footer"];// 若要使用自定义的表头表尾, 只要注册对应自定义类名即可.// 若要使用多种样式的表头或表尾, 就需要多个注册表头或者表尾的语句
// 重用表头表尾的方法// 创建表头表尾- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {    // 判断返回表头类型 还是表尾类型    if ([kind isEqualToString:UICollectionElementKindSectionHeader]) {        // 表头        // 去重用池里找 判断一下  有就用  没有就创建        UICollectionReusableView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"header" forIndexPath:indexPath];        headerView.backgroundColor = [UIColor magentaColor];        return headerView;    } else {        // 表尾        UICollectionReusableView *rootView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"footer" forIndexPath:indexPath];        rootView.backgroundColor = [UIColor yellowColor];        return rootView;    }}
1 0
原创粉丝点击