iOS-UICollectionView入門

一、UICollectionView介紹

UICollectionView和UICollectionViewController類是iOS6新引進(jìn)的API,用于展示集合視圖,布局更加靈活,可實(shí)現(xiàn)多列布局,用法類似于UITableView和UITableViewController類,但也有所不同。

UICollectionView可以實(shí)現(xiàn)如下效果,也是一個(gè)常用的控件:

二、UICollectiomView使用

UICollectionView的創(chuàng)建和UITableView的創(chuàng)建有所不同:

UITableView的創(chuàng)建只需要設(shè)置frame即可使用

UICollectionView除了需要frame,還需要一個(gè)布局參數(shù)

-(id)initWithFrame:(CGRect)frame /* 尺寸 */

collectionViewLayout:(UICollectionViewLayout *)layout;/* 布局參數(shù) */

UITableView可以不需要注冊Cell視圖類,手動(dòng)創(chuàng)建Cell視圖類

UICollectionView必須注冊視圖類,才能顯示,不需要手動(dòng)創(chuàng)建

UICollectionView的布局參數(shù):

1.是一個(gè)UICollectionViewLayout類的對象,

但我們一般使用它的子類UICollectionViewFlowLayout

2.設(shè)置布局對象的滾動(dòng)方向?qū)傩詓crollDirection:

typedef NS_ENUM(NSInteger, UICollectionViewScrollDirection) {

UICollectionViewScrollDirectionVertical,? /*垂直滾動(dòng)*/

UICollectionViewScrollDirectionHorizontal /* 水平滾動(dòng) */

};

3.垂直滾動(dòng),表示Cell方塊布局是從左往右,從上到下排列的布局

4.水平滾動(dòng),表示Cell方塊布局是從上往下,從左到右排列的布局

5.和UITableView不同,UICollectionView只能在這里設(shè)置頂部視圖和底部視圖的大小

6.設(shè)置為垂直滾動(dòng)時(shí),頂部和底部視圖的寬度為UICollectionView的寬度,無法設(shè)置

7.設(shè)置為水平滾動(dòng)時(shí),頂部和底部視圖的高度為UICollectionView的高度,無法設(shè)置

UICollectionView的常用對象方法

/* 向容器視圖注冊Cell方塊視圖,有2種方式,一種是類名注冊,一種是Xib注冊 */

- (void)registerClass:(Class)cellClass /* 視圖類 */

forCellWithReuseIdentifier:(NSString *)identifier;/* 綁定標(biāo)識 */

- (void)registerNib:(UINib *)nib /* Xib */

forCellWithReuseIdentifier:(NSString *)identifier;/* 綁定標(biāo)識 */

/* 從緩存池中取出Cell方塊視圖對象,如果緩存池沒有,自動(dòng)調(diào)用alloc/initWithFrame創(chuàng)建 */

- (UICollectionViewCell *)dequeueReusableCellWithReuseIdentifier:(NSString *)identifier

forIndexPath:(NSIndexPath *)indexPath;

/* kind參數(shù)設(shè)置 */

NSString *const UICollectionElementKindSectionHeader;/* 頂部視圖用這個(gè) */

NSString *const UICollectionElementKindSectionFooter;/* 底部視圖用這個(gè) */

/* 向容器視圖注冊頂部視圖或者底部視圖,有2種方式,一種是類名注冊,一種是Xib注冊 */

- (void)registerClass:(Class)viewClass

forSupplementaryViewOfKind:(NSString *)kind /* 參考上面 */

withReuseIdentifier:(NSString *)identifier;/* 綁定標(biāo)識 */

- (void)registerNib:(UINib *)nib

forSupplementaryViewOfKind:(NSString *)kind /* 參考上面 */

withReuseIdentifier:(NSString *)identifier;/* 綁定標(biāo)識 */

/* 從緩存池中取出頂部視圖對象或者底部視圖對象,如果緩存池沒有,自動(dòng)調(diào)用alloc/initWithFrame創(chuàng)建 */

- (UICollectionReusableView *)dequeueReusableSupplementaryViewOfKind:(NSString *)kind

withReuseIdentifier:(NSString *)identifier

forIndexPath:(NSIndexPath *)indexPath;

UICollectionView的數(shù)據(jù)源方法

@required

/* 設(shè)置容器視圖各個(gè)組都有多少個(gè)Cell方塊 */

- (NSInteger)collectionView:(UICollectionView *)collectionView

numberOfItemsInSection:(NSInteger)section;

/* 設(shè)置Cell方塊視圖,類似于UITableViewCell的設(shè)置 */

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView

cellForItemAtIndexPath:(NSIndexPath *)indexPath;

@optional

/* 容器視圖有多少個(gè)組,默認(rèn)返回1 */

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView;

/* 設(shè)置頂部視圖和底部視圖,通過kind參數(shù)分辨是設(shè)置頂部還是底部 */

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView

viewForSupplementaryElementOfKind:(NSString *)kind

atIndexPath:(NSIndexPath *)indexPath;

UICollectionViewDelegate的常用方法

/* 選中Cell方塊時(shí)調(diào)用 */

- (void)collectionView:(UICollectionView *)collectionView

didSelectItemAtIndexPath:(NSIndexPath *)indexPath;

/* 取消選中Cell方塊時(shí)調(diào)用 */

- (void)collectionView:(UICollectionView *)collectionView

didDeselectItemAtIndexPath:(NSIndexPath *)indexPath;

我們使用更多的是UICollectionViewDelegate子協(xié)議UICollectionViewDelegateFlowLayout

該協(xié)議不僅包含父協(xié)議所有方法,還可以進(jìn)行一些布局設(shè)置

UICollectionViewDelegateFlowLayout的常用布局方法

/* 設(shè)置每個(gè)方塊的尺寸大小 */

- (CGSize)collectionView:(UICollectionView *)collectionView

layout:(UICollectionViewLayout*)collectionViewLayout

sizeForItemAtIndexPath:(NSIndexPath *)indexPath;

/* 設(shè)置方塊視圖和邊界的上下左右間距 */

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView

layout:(UICollectionViewLayout*)collectionViewLayout

insetForSectionAtIndex:(NSInteger)section;


下面是我自定義的Cell視圖類、頂部視圖類、底部視圖類,目錄結(jié)構(gòu)如下:


方塊視圖LTCollectionViewCell.h

#import "LTCollectionViewCell.h"

@interface LTCollectionViewCell : UICollectionViewCell

@property (strong, nonatomic) UILabel *textLabel;

/* 方塊視圖的緩存池標(biāo)示 */

+ (NSString *)cellIdentifier;

/* 獲取方塊視圖對象 */

+ (instancetype)cellWithCollectionView:(UICollectionView *)collectionView

forIndexPath:(NSIndexPath *)indexPath;

@end

方塊視圖LTCollectionViewCell.m

#import "LTCollectionViewCell.h"

@implementation LTCollectionViewCell

/* 方塊視圖的緩存池標(biāo)示 */

+ (NSString *)cellIdentifier{

static NSString *cellIdentifier = @"CollectionViewCellIdentifier";

return cellIdentifier;

? }?

/* 獲取方塊視圖對象 */

+ (instancetype)cellWithCollectionView:(UICollectionView *)collectionView

forIndexPath:(NSIndexPath *)indexPath

{

//從緩存池中尋找方塊視圖對象,如果沒有,該方法自動(dòng)調(diào)用alloc/initWithFrame創(chuàng)建一個(gè)新的方塊視圖返回

LTCollectionViewCell *cell =

[collectionView dequeueReusableCellWithReuseIdentifier:[LTCollectionViewCell cellIdentifier]

forIndexPath:indexPath];

return cell;

? }

/* 注冊了方塊視圖后,當(dāng)緩存池中沒有底部視圖的對象時(shí)候,自動(dòng)調(diào)用alloc/initWithFrame創(chuàng)建 */

- (instancetype)initWithFrame:(CGRect)frame{

if (self = [super initWithFrame:frame]) {

//創(chuàng)建label

UILabel *textLabel = [[UILabel alloc] init];

//設(shè)置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);

//設(shè)置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;

/* 頂部視圖的緩存池標(biāo)示 */

+ (NSString *)headerViewIdentifier;

/* 獲取頂部視圖對象 */

+ (instancetype)headerViewWithCollectionView:(UICollectionView *)collectionView

forIndexPath:(NSIndexPath *)indexPath;

@end

頂部視圖LTCollectionHeaderView.m

#import "LTCollectionHeaderView.h"

@implementation LTCollectionHeaderView

/* 頂部視圖的緩存池標(biāo)示 */

+ (NSString *)headerViewIdentifier{

static NSString *headerIdentifier = @"headerViewIdentifier";

return headerIdentifier;

?}

/* 獲取頂部視圖對象 */

+ (instancetype)headerViewWithCollectionView:(UICollectionView *)collectionView

forIndexPath:(NSIndexPath *)indexPath

{

//從緩存池中尋找頂部視圖對象,如果沒有,該方法自動(dòng)調(diào)用alloc/initWithFrame創(chuàng)建一個(gè)新的頂部視圖返回

LTCollectionHeaderView *headerView =

[collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader

withReuseIdentifier:[LTCollectionHeaderView headerViewIdentifier]

forIndexPath:indexPath];

return headerView;

?}

/* 注冊了頂部視圖后,當(dāng)緩存池中沒有頂部視圖的對象時(shí)候,自動(dòng)調(diào)用alloc/initWithFrame創(chuàng)建 */

- (instancetype)initWithFrame:(CGRect)frame{

if (self = [super initWithFrame:frame]) {

//創(chuàng)建label

UILabel *textLabel = [[UILabel alloc] init];

//設(shè)置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);

//設(shè)置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;

/* 底部視圖的緩存池標(biāo)示 */

+ (NSString *)footerViewIdentifier;

/* 獲取底部視圖對象 */

+ (instancetype)footerViewWithCollectionView:(UICollectionView *)collectionView

forIndexPath:(NSIndexPath *)indexPath;

@end

底部視圖LTCollectionFooterView.m

#import "LTCollectionFooterView.h"

@implementation LTCollectionFooterView

/* 底部視圖的緩存池標(biāo)示 */

+ (NSString *)footerViewIdentifier{

static NSString *footerIdentifier = @"footerViewIdentifier";

return footerIdentifier;

?}

/* 獲取底部視圖對象 */

+ (instancetype)footerViewWithCollectionView:(UICollectionView *)collectionView

forIndexPath:(NSIndexPath *)indexPath

{

//從緩存池中尋找底部視圖對象,如果沒有,該方法自動(dòng)調(diào)用alloc/initWithFrame創(chuàng)建一個(gè)新的底部視圖返回

LTCollectionFooterView *footerView =

[collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter

withReuseIdentifier:[LTCollectionFooterView footerViewIdentifier]

forIndexPath:indexPath];

return footerView;

?}

/* 注冊了底部視圖后,當(dāng)緩存池中沒有底部視圖的對象時(shí)候,自動(dòng)調(diào)用alloc/initWithFrame創(chuàng)建 */

- (instancetype)initWithFrame:(CGRect)frame{

if (self = [super initWithFrame:frame]) {

//創(chuàng)建label

UILabel *textLabel = [[UILabel alloc] init];

//設(shè)置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);

//設(shè)置label屬性

textLabel.numberOfLines = 0;

textLabel.textAlignment = NSTextAlignmentCenter;

//添加到父控件

[self addSubview:textLabel];

self.textLabel = textLabel;

?}

return self;

}

@end

下面是使用實(shí)例:

1. 視圖控制器屬性和相關(guān)方法

#import "ViewController.h"

#import "LTCollectionViewCell.h"

#import "LTCollectionHeaderView.h"

#import "LTCollectionFooterView.h"

@interface ViewController ()@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;

//創(chuàng)建布局對象

UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];

//設(shè)置滾動(dòng)方向?yàn)榇怪睗L動(dòng),說明方塊是從左上到右下的布局排列方式

layout.scrollDirection = UICollectionViewScrollDirectionVertical;

//設(shè)置頂部視圖和底部視圖的大小,當(dāng)滾動(dòng)方向?yàn)榇怪睍r(shí),設(shè)置寬度無效,當(dāng)滾動(dòng)方向?yàn)樗綍r(shí),設(shè)置高度無效

layout.headerReferenceSize = CGSizeMake(100, 40);

layout.footerReferenceSize = CGSizeMake(100, 40);

//創(chuàng)建容器視圖

CGRect frame = CGRectMake(x, y, width, height);

UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:frame

collectionViewLayout:layout];

collectionView.delegate = self;//設(shè)置代理

collectionView.dataSource = self;//設(shè)置數(shù)據(jù)源

collectionView.backgroundColor = [UIColor whiteColor];//設(shè)置背景,默認(rèn)為黑色

//添加到主視圖

[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數(shù)據(jù)源方法

#pragma mark - UICollectionViewDataSource

/* 設(shè)置容器中有多少個(gè)組 */

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{

return 10;

?}

/* 設(shè)置每個(gè)組有多少個(gè)方塊 */

- (NSInteger)collectionView:(UICollectionView *)collectionView

numberOfItemsInSection:(NSInteger)section

{

return 20;

?}

/* 設(shè)置方塊的視圖 */

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView

cellForItemAtIndexPath:(NSIndexPath *)indexPath

{

//獲取cell視圖,內(nèi)部通過去緩存池中取,如果緩存池中沒有,就自動(dòng)創(chuàng)建一個(gè)新的cell

LTCollectionViewCell *cell =

[LTCollectionViewCell cellWithCollectionView:collectionView

forIndexPath:indexPath];

//設(shè)置cell屬性

cell.contentView.backgroundColor = [UIColor redColor];

cell.textLabel.text = [NSString stringWithFormat:@"Cell %2ld",indexPath.row];

return cell;

?}

/* 設(shè)置頂部視圖和底部視圖 */

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView

viewForSupplementaryElementOfKind:(NSString *)kind

atIndexPath:(NSIndexPath *)indexPath

{

if ( [kind isEqualToString:UICollectionElementKindSectionHeader] ) {//頂部視圖

//獲取頂部視圖

LTCollectionHeaderView *headerView =

[LTCollectionHeaderView headerViewWithCollectionView:collectionView

forIndexPath:indexPath];

//設(shè)置頂部視圖屬性

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];

//設(shè)置底部視圖屬性

footerView.backgroundColor = [UIColor greenColor];

footerView.textLabel.text = [NSString stringWithFormat:@"-Footer-%ld-",indexPath.section];

return footerView;

?}?

return nil;

}

4. UICollectionViewDelegateFlowLayout布局代理方法

#pragma mark - UICollectionViewDelegateFlowLayout

/* 設(shè)置各個(gè)方塊的大小尺寸 */

- (CGSize)collectionView:(UICollectionView *)collectionView

layout:(UICollectionViewLayout*)collectionViewLayout

sizeForItemAtIndexPath:(NSIndexPath *)indexPath

{

CGFloat width = 50;

CGFloat height = 50;

return CGSizeMake(width, height);

?}

/* 設(shè)置每一組的上下左右間距 */

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView

layout:(UICollectionViewLayout*)collectionViewLayout

insetForSectionAtIndex:(NSInteger)section

{

return UIEdgeInsetsMake(10, 10, 10, 10);

}

5. 父協(xié)議UICollectionViewDelegate的代理方法

#pragma mark - UICollectionViewDelegate

/* 方塊被選中會調(diào)用 */

- (void)collectionView:(UICollectionView *)collectionView

didSelectItemAtIndexPath:(NSIndexPath *)indexPath

{

NSLog(@"點(diǎn)擊選擇了第%ld組第%ld個(gè)方塊",indexPath.section,indexPath.row);

?}

/* 方塊取消選中會調(diào)用 */

- (void)collectionView:(UICollectionView *)collectionView

didDeselectItemAtIndexPath:(NSIndexPath *)indexPath

{

NSLog(@"取消選擇第%ld組第%ld個(gè)方塊",indexPath.section,indexPath.row);

}

@end

效果圖如下,左邊為垂直滾動(dòng)效果,右邊為水平滾動(dòng)效果


如果修改下布局代理方法的上下左右邊界距離:

/* 設(shè)置每一組的上下左右間距 */

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView

layout:(UICollectionViewLayout*)collectionViewLayout

insetForSectionAtIndex:(NSInteger)section

{

return UIEdgeInsetsMake(0, 0, 0, 0);

}



LearnDemo里面的CollectionViewDemo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容