iOS学习笔记33-UICollectionView入门

来源:互联网 发布:前瞻网数据库会员 编辑:程序博客网 时间:2024/06/17 18:03

一、UICollectionView介绍

UICollectionViewUICollectionViewController类是iOS6新引进的API,用于展示集合视图,布局更加灵活,可实现多列布局,用法类似于UITableViewUITableViewController类,但也有所不同。
UICollectionView可以实现如下效果,也是一个常用的控件:

二、UICollectiomView使用

UICollectionView的创建和UITableView的创建有所不同:
1. UITableView的创建只需要设置frame即可使用
UICollectionView除了需要frame,还需要一个布局参数

-(id)initWithFrame:(CGRect)frame /* 尺寸 */        collectionViewLayout:(UICollectionViewLayout *)layout;/* 布局参数 */
  1. UITableView可以不需要注册Cell视图类,手动创建Cell视图类
    UICollectionView必须注册视图类,才能显示,不需要手动创建
UICollectionView的布局参数:
  1. 是一个UICollectionViewLayout类的对象,
    但我们一般使用它的子类UICollectionViewFlowLayout
  2. 设置布局对象的滚动方向属性scrollDirection
typedef NS_ENUM(NSInteger, UICollectionViewScrollDirection) {             UICollectionViewScrollDirectionVertical,  /*垂直滚动*/          UICollectionViewScrollDirectionHorizontal /* 水平滚动 */};
  1. 垂直滚动,表示Cell方块布局是从左往右,从上到下排列的布局
  2. 水平滚动,表示Cell方块布局是从上往下,从左到右排列的布局
  3. UITableView不同,UICollectionView只能在这里设置顶部视图和底部视图的大小
  4. 设置为垂直滚动时,顶部和底部视图的宽度为UICollectionView的宽度,无法设置
  5. 设置为水平滚动时,顶部和底部视图的高度为UICollectionView的高度,无法设置
UICollectionView的常用对象方法
/* 向容器视图注册Cell方块视图,有2种方式,一种是类名注册,一种是Xib注册 */- (void)registerClass:(Class)cellClass /* 视图类 */        forCellWithReuseIdentifier:(NSString *)identifier;/* 绑定标识 */- (void)registerNib:(UINib *)nib /* Xib */        forCellWithReuseIdentifier:(NSString *)identifier;/* 绑定标识 *//* 从缓存池中取出Cell方块视图对象,如果缓存池没有,自动调用alloc/initWithFrame创建 */- (UICollectionViewCell *)dequeueReusableCellWithReuseIdentifier:(NSString *)identifier                           forIndexPath:(NSIndexPath *)indexPath;/* kind参数设置 */NSString *const UICollectionElementKindSectionHeader;/* 顶部视图用这个 */NSString *const UICollectionElementKindSectionFooter;/* 底部视图用这个 *//* 向容器视图注册顶部视图或者底部视图,有2种方式,一种是类名注册,一种是Xib注册 */- (void)registerClass:(Class)viewClass         forSupplementaryViewOfKind:(NSString *)kind /* 参考上面 */               withReuseIdentifier:(NSString *)identifier;/* 绑定标识 */- (void)registerNib:(UINib *)nib         forSupplementaryViewOfKind:(NSString *)kind /* 参考上面 */               withReuseIdentifier:(NSString *)identifier;/* 绑定标识 *//* 从缓存池中取出顶部视图对象或者底部视图对象,如果缓存池没有,自动调用alloc/initWithFrame创建 */- (UICollectionReusableView *)dequeueReusableSupplementaryViewOfKind:(NSString *)kind                               withReuseIdentifier:(NSString *)identifier                                      forIndexPath:(NSIndexPath *)indexPath;
UICollectionView的数据源方法
@required/* 设置容器视图各个组都有多少个Cell方块 */- (NSInteger)collectionView:(UICollectionView *)collectionView      numberOfItemsInSection:(NSInteger)section;/* 设置Cell方块视图,类似于UITableViewCell的设置 */- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView                   cellForItemAtIndexPath:(NSIndexPath *)indexPath;@optional/* 容器视图有多少个组,默认返回1 */- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView;/* 设置顶部视图和底部视图,通过kind参数分辨是设置顶部还是底部 */- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView            viewForSupplementaryElementOfKind:(NSString *)kind                                  atIndexPath:(NSIndexPath *)indexPath;
UICollectionViewDelegate的常用方法
/* 选中Cell方块时调用 */- (void)collectionView:(UICollectionView *)collectionView         didSelectItemAtIndexPath:(NSIndexPath *)indexPath;/* 取消选中Cell方块时调用 */- (void)collectionView:(UICollectionView *)collectionView         didDeselectItemAtIndexPath:(NSIndexPath *)indexPath;

我们使用更多的是UICollectionViewDelegate子协议UICollectionViewDelegateFlowLayout
该协议不仅包含父协议所有方法,还可以进行一些布局设置

UICollectionViewDelegateFlowLayout的常用布局方法
/* 设置每个方块的尺寸大小 */- (CGSize)collectionView:(UICollectionView *)collectionView                   layout:(UICollectionViewLayout*)collectionViewLayout   sizeForItemAtIndexPath:(NSIndexPath *)indexPath;/* 设置方块视图和边界的上下左右间距 */- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView                         layout:(UICollectionViewLayout*)collectionViewLayout         insetForSectionAtIndex:(NSInteger)section;

下面是我自定义的Cell视图类、顶部视图类、底部视图类,目录结构如下:

方块视图LTCollectionViewCell.h
#import <UIKit/UIKit.h>@interface LTCollectionViewCell : UICollectionViewCell@property (strong, nonatomic) UILabel *textLabel;/* 方块视图的缓存池标示 */+ (NSString *)cellIdentifier;/* 获取方块视图对象 */+ (instancetype)cellWithCollectionView:(UICollectionView *)collectionView                          forIndexPath:(NSIndexPath *)indexPath;@end
方块视图LTCollectionViewCell.m
#import "LTCollectionViewCell.h"@implementation LTCollectionViewCell/* 方块视图的缓存池标示 */+ (NSString *)cellIdentifier{    static NSString *cellIdentifier = @"CollectionViewCellIdentifier";    return cellIdentifier;}/* 获取方块视图对象 */+ (instancetype)cellWithCollectionView:(UICollectionView *)collectionView                          forIndexPath:(NSIndexPath *)indexPath{    //从缓存池中寻找方块视图对象,如果没有,该方法自动调用alloc/initWithFrame创建一个新的方块视图返回    LTCollectionViewCell *cell =         [collectionView dequeueReusableCellWithReuseIdentifier:[LTCollectionViewCell cellIdentifier]                                                  forIndexPath:indexPath];    return cell;}/* 注册了方块视图后,当缓存池中没有底部视图的对象时候,自动调用alloc/initWithFrame创建 */- (instancetype)initWithFrame:(CGRect)frame{    if (self = [super initWithFrame:frame]) {        //创建label        UILabel *textLabel = [[UILabel alloc] init];        //设置label尺寸        CGFloat x = 5;        CGFloat y = 5;        CGFloat width = frame.size.width - 10;        CGFloat height = frame.size.height - 10;        textLabel.frame = CGRectMake(x, y, width, height);        //设置label属性        textLabel.numberOfLines = 0;        textLabel.textAlignment = NSTextAlignmentCenter;        textLabel.font = [UIFont systemFontOfSize:15];        //添加到父控件        [self.contentView addSubview:textLabel];        self.textLabel = textLabel;    }    return self;}@end
顶部视图LTCollectionHeaderView.h
#import <UIKit/UIKit.h>@interface LTCollectionHeaderView : UICollectionReusableView@property (strong, nonatomic) UILabel *textLabel;/* 顶部视图的缓存池标示 */+ (NSString *)headerViewIdentifier;/* 获取顶部视图对象 */+ (instancetype)headerViewWithCollectionView:(UICollectionView *)collectionView                                forIndexPath:(NSIndexPath *)indexPath;@end
顶部视图LTCollectionHeaderView.m
#import "LTCollectionHeaderView.h"@implementation LTCollectionHeaderView/* 顶部视图的缓存池标示 */+ (NSString *)headerViewIdentifier{    static NSString *headerIdentifier = @"headerViewIdentifier";    return headerIdentifier;}/* 获取顶部视图对象 */+ (instancetype)headerViewWithCollectionView:(UICollectionView *)collectionView                                 forIndexPath:(NSIndexPath *)indexPath{    //从缓存池中寻找顶部视图对象,如果没有,该方法自动调用alloc/initWithFrame创建一个新的顶部视图返回    LTCollectionHeaderView *headerView =         [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader                                           withReuseIdentifier:[LTCollectionHeaderView headerViewIdentifier]                                                  forIndexPath:indexPath];    return headerView;}/* 注册了顶部视图后,当缓存池中没有顶部视图的对象时候,自动调用alloc/initWithFrame创建 */- (instancetype)initWithFrame:(CGRect)frame{    if (self = [super initWithFrame:frame]) {        //创建label        UILabel *textLabel = [[UILabel alloc] init];        //设置label尺寸        CGFloat x = 5;        CGFloat y = 5;        CGFloat width = frame.size.width - 10;        CGFloat height = frame.size.height - 10;        textLabel.frame = CGRectMake(x, y, width, height);        //设置label属性        textLabel.numberOfLines = 0;        textLabel.textAlignment = NSTextAlignmentCenter;        //添加到父控件        [self addSubview:textLabel];        self.textLabel = textLabel;    }    return self;}@end
底部视图LTCollectionFooterView.h
#import <UIKit/UIKit.h>@interface LTCollectionFooterView : UICollectionReusableView@property (strong, nonatomic) UILabel *textLabel;/* 底部视图的缓存池标示 */+ (NSString *)footerViewIdentifier;/* 获取底部视图对象 */+ (instancetype)footerViewWithCollectionView:(UICollectionView *)collectionView                                forIndexPath:(NSIndexPath *)indexPath;@end
底部视图LTCollectionFooterView.m
#import "LTCollectionFooterView.h"@implementation LTCollectionFooterView/* 底部视图的缓存池标示 */+ (NSString *)footerViewIdentifier{    static NSString *footerIdentifier = @"footerViewIdentifier";    return footerIdentifier;}/* 获取底部视图对象 */+ (instancetype)footerViewWithCollectionView:(UICollectionView *)collectionView                                forIndexPath:(NSIndexPath *)indexPath{    //从缓存池中寻找底部视图对象,如果没有,该方法自动调用alloc/initWithFrame创建一个新的底部视图返回    LTCollectionFooterView *footerView =            [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter                                               withReuseIdentifier:[LTCollectionFooterView footerViewIdentifier]                                                      forIndexPath:indexPath];    return footerView;}/* 注册了底部视图后,当缓存池中没有底部视图的对象时候,自动调用alloc/initWithFrame创建 */- (instancetype)initWithFrame:(CGRect)frame{    if (self = [super initWithFrame:frame]) {        //创建label        UILabel *textLabel = [[UILabel alloc] init];        //设置label尺寸        CGFloat x = 5;        CGFloat y = 5;        CGFloat width = frame.size.width - 10;        CGFloat height = frame.size.height - 10;        textLabel.frame = CGRectMake(x, y, width, height);        //设置label属性        textLabel.numberOfLines = 0;        textLabel.textAlignment = NSTextAlignmentCenter;        //添加到父控件        [self addSubview:textLabel];        self.textLabel = textLabel;    }    return self;}@end
下面是使用实例:
1. 视图控制器属性和相关方法
#import "ViewController.h"#import "LTCollectionViewCell.h"#import "LTCollectionHeaderView.h"#import "LTCollectionFooterView.h"@interface ViewController () <UICollectionViewDataSource,                              UICollectionViewDelegateFlowLayout>@property (strong, nonatomic) UICollectionView *collectionView;/*< 容器视图 */@end@implementation ViewController- (void)viewDidLoad {    [super viewDidLoad];    //初始化容器视图    [self initCollectionView];}
2. 初始化容器视图
/* 初始化容器视图 */- (void)initCollectionView{    CGFloat x = 0;    CGFloat y = 20;    CGFloat width = self.view.frame.size.width;    CGFloat height = self.view.frame.size.height - 20;    //创建布局对象    UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];    //设置滚动方向为垂直滚动,说明方块是从左上到右下的布局排列方式    layout.scrollDirection = UICollectionViewScrollDirectionVertical;    //设置顶部视图和底部视图的大小,当滚动方向为垂直时,设置宽度无效,当滚动方向为水平时,设置高度无效    layout.headerReferenceSize = CGSizeMake(100, 40);    layout.footerReferenceSize = CGSizeMake(100, 40);    //创建容器视图    CGRect frame = CGRectMake(x, y, width, height);    UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:frame                                                          collectionViewLayout:layout];    collectionView.delegate = self;//设置代理    collectionView.dataSource = self;//设置数据源    collectionView.backgroundColor = [UIColor whiteColor];//设置背景,默认为黑色    //添加到主视图    [self.view addSubview:collectionView];    self.collectionView = collectionView;    //注册容器视图中显示的方块视图    [collectionView registerClass:[LTCollectionViewCell class]            forCellWithReuseIdentifier:[LTCollectionViewCell cellIdentifier]];    //注册容器视图中显示的顶部视图    [collectionView registerClass:[LTCollectionHeaderView class]       forSupplementaryViewOfKind:UICollectionElementKindSectionHeader              withReuseIdentifier:[LTCollectionHeaderView headerViewIdentifier]];    //注册容器视图中显示的底部视图    [collectionView registerClass:[LTCollectionFooterView class]       forSupplementaryViewOfKind:UICollectionElementKindSectionFooter              withReuseIdentifier:[LTCollectionFooterView footerViewIdentifier]];}
3. UICollectionViewDataSource数据源方法
#pragma mark - UICollectionViewDataSource/* 设置容器中有多少个组 */- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{    return 10;}/* 设置每个组有多少个方块 */- (NSInteger)collectionView:(UICollectionView *)collectionView     numberOfItemsInSection:(NSInteger)section{    return 20;}/* 设置方块的视图 */- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView                  cellForItemAtIndexPath:(NSIndexPath *)indexPath{    //获取cell视图,内部通过去缓存池中取,如果缓存池中没有,就自动创建一个新的cell    LTCollectionViewCell *cell =             [LTCollectionViewCell cellWithCollectionView:collectionView                                            forIndexPath:indexPath];    //设置cell属性    cell.contentView.backgroundColor = [UIColor redColor];    cell.textLabel.text = [NSString stringWithFormat:@"Cell %2ld",indexPath.row];    return cell;}/* 设置顶部视图和底部视图 */- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView           viewForSupplementaryElementOfKind:(NSString *)kind                                 atIndexPath:(NSIndexPath *)indexPath{    if ( [kind isEqualToString:UICollectionElementKindSectionHeader] ) {//顶部视图        //获取顶部视图        LTCollectionHeaderView *headerView =             [LTCollectionHeaderView headerViewWithCollectionView:collectionView                                                    forIndexPath:indexPath];        //设置顶部视图属性        headerView.backgroundColor = [UIColor orangeColor];        headerView.textLabel.text = [NSString stringWithFormat:@"-Header-%ld-",indexPath.section];        return headerView;    } else if( [kind isEqualToString:UICollectionElementKindSectionFooter] ) {//底部视图        //获取底部视图        LTCollectionFooterView *footerView =              [LTCollectionFooterView footerViewWithCollectionView:collectionView                                                     forIndexPath:indexPath];        //设置底部视图属性        footerView.backgroundColor = [UIColor greenColor];        footerView.textLabel.text = [NSString stringWithFormat:@"-Footer-%ld-",indexPath.section];        return footerView;    }    return nil;}
4. UICollectionViewDelegateFlowLayout布局代理方法
#pragma mark - UICollectionViewDelegateFlowLayout/* 设置各个方块的大小尺寸 */- (CGSize)collectionView:(UICollectionView *)collectionView                  layout:(UICollectionViewLayout*)collectionViewLayout  sizeForItemAtIndexPath:(NSIndexPath *)indexPath{    CGFloat width = 50;    CGFloat height = 50;    return CGSizeMake(width, height);}/* 设置每一组的上下左右间距 */- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView                        layout:(UICollectionViewLayout*)collectionViewLayout        insetForSectionAtIndex:(NSInteger)section{    return UIEdgeInsetsMake(10, 10, 10, 10);}
5. 父协议UICollectionViewDelegate的代理方法
#pragma mark - UICollectionViewDelegate/* 方块被选中会调用 */- (void)collectionView:(UICollectionView *)collectionView        didSelectItemAtIndexPath:(NSIndexPath *)indexPath{    NSLog(@"点击选择了第%ld组第%ld个方块",indexPath.section,indexPath.row);}/* 方块取消选中会调用 */- (void)collectionView:(UICollectionView *)collectionView        didDeselectItemAtIndexPath:(NSIndexPath *)indexPath{    NSLog(@"取消选择第%ld组第%ld个方块",indexPath.section,indexPath.row);}@end
效果图如下,左边为垂直滚动效果,右边为水平滚动效果

如果修改下布局代理方法的上下左右边界距离:
/* 设置每一组的上下左右间距 */- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView                        layout:(UICollectionViewLayout*)collectionViewLayout        insetForSectionAtIndex:(NSInteger)section{    return UIEdgeInsetsMake(0, 0, 0, 0);}

上面的代码Demo点这里:LearnDemo里面的CollectionViewDemo

如果有什么问题可以在下方评论区中提出!O(∩_∩)O哈!
0 0