UICollectionView
和UICollectionViewController
類是iOS6新引進的API,用於展現集合視圖,佈局更加靈活,可實現多列布局,用法相似於UITableView
和UITableViewController
類,但也有所不一樣。
UICollectionView
能夠實現以下效果,也是一個經常使用的控件:
git
UICollectionView
的建立和UITableView
的建立有所不一樣:github
UITableView
的建立只須要設置frame
便可使用UICollectionView
除了須要frame
,還須要一個佈局參數-(id)initWithFrame:(CGRect)frame /* 尺寸 */ collectionViewLayout:(UICollectionViewLayout *)layout;/* 佈局參數 */
UITableView
能夠不須要註冊Cell視圖類,手動建立Cell視圖類UICollectionView
必須註冊視圖類,才能顯示,不須要手動建立UICollectionViewLayout
類的對象,UICollectionViewFlowLayout
scrollDirection
:typedef NS_ENUM(NSInteger, UICollectionViewScrollDirection) { UICollectionViewScrollDirectionVertical, /*垂直滾動*/ UICollectionViewScrollDirectionHorizontal /* 水平滾動 */ };
UITableView
不一樣,UICollectionView
只能在這裏設置頂部視圖和底部視圖的大小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;
@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;
/* 選中Cell方塊時調用 */ - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath; /* 取消選中Cell方塊時調用 */ - (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath;
咱們使用更多的是UICollectionViewDelegate
子協議UICollectionViewDelegateFlowLayout
該協議不只包含父協議全部方法,還能夠進行一些佈局設置緩存
/* 設置每一個方塊的尺寸大小 */ - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath; /* 設置方塊視圖和邊界的上下左右間距 */ - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section;
#import <UIKit/UIKit.h> @interface LTCollectionViewCell : UICollectionViewCell @property (strong, nonatomic) UILabel *textLabel; /* 方塊視圖的緩存池標示 */ + (NSString *)cellIdentifier; /* 獲取方塊視圖對象 */ + (instancetype)cellWithCollectionView:(UICollectionView *)collectionView forIndexPath:(NSIndexPath *)indexPath; @end
#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
#import <UIKit/UIKit.h> @interface LTCollectionHeaderView : UICollectionReusableView @property (strong, nonatomic) UILabel *textLabel; /* 頂部視圖的緩存池標示 */ + (NSString *)headerViewIdentifier; /* 獲取頂部視圖對象 */ + (instancetype)headerViewWithCollectionView:(UICollectionView *)collectionView forIndexPath:(NSIndexPath *)indexPath; @end
#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
#import <UIKit/UIKit.h> @interface LTCollectionFooterView : UICollectionReusableView @property (strong, nonatomic) UILabel *textLabel; /* 底部視圖的緩存池標示 */ + (NSString *)footerViewIdentifier; /* 獲取底部視圖對象 */ + (instancetype)footerViewWithCollectionView:(UICollectionView *)collectionView forIndexPath:(NSIndexPath *)indexPath; @end
#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
#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]; }
/* 初始化容器視圖 */ - (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]]; }
#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; }
#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); }
#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裏面的CollectionViewDemoide