一唇敞、UICollectionView介紹
UICollectionView和UICollectionViewController類是iOS6新引進的API煌集,用于展示集合視圖,布局更加靈活败京,可實現(xiàn)多列布局,用法類似于UITableView和UITableViewController類涩哟,但也有所不同。
UICollectionView可以實現(xiàn)如下效果诗鸭,也是一個常用的控件:
二染簇、UICollectiomView使用
UICollectionView的創(chuàng)建和UITableView的創(chuàng)建有所不同:
UITableView的創(chuàng)建只需要設(shè)置frame即可使用
UICollectionView除了需要frame,還需要一個布局參數(shù)
-(id)initWithFrame:(CGRect)frame /* 尺寸 */
collectionViewLayout:(UICollectionViewLayout *)layout;/* 布局參數(shù) */
UITableView可以不需要注冊Cell視圖類强岸,手動創(chuàng)建Cell視圖類
UICollectionView必須注冊視圖類锻弓,才能顯示,不需要手動創(chuàng)建
UICollectionView的布局參數(shù):
1.是一個UICollectionViewLayout類的對象蝌箍,
但我們一般使用它的子類UICollectionViewFlowLayout
2.設(shè)置布局對象的滾動方向?qū)傩詓crollDirection:
typedef NS_ENUM(NSInteger, UICollectionViewScrollDirection) {
UICollectionViewScrollDirectionVertical,? /*垂直滾動*/
UICollectionViewScrollDirectionHorizontal /* 水平滾動 */
};
3.垂直滾動青灼,表示Cell方塊布局是從左往右,從上到下排列的布局
4.水平滾動妓盲,表示Cell方塊布局是從上往下杂拨,從左到右排列的布局
5.和UITableView不同,UICollectionView只能在這里設(shè)置頂部視圖和底部視圖的大小
6.設(shè)置為垂直滾動時悯衬,頂部和底部視圖的寬度為UICollectionView的寬度弹沽,無法設(shè)置
7.設(shè)置為水平滾動時,頂部和底部視圖的高度為UICollectionView的高度筋粗,無法設(shè)置
UICollectionView的常用對象方法
/* 向容器視圖注冊Cell方塊視圖策橘,有2種方式,一種是類名注冊娜亿,一種是Xib注冊 */
- (void)registerClass:(Class)cellClass /* 視圖類 */
forCellWithReuseIdentifier:(NSString *)identifier;/* 綁定標識 */
- (void)registerNib:(UINib *)nib /* Xib */
forCellWithReuseIdentifier:(NSString *)identifier;/* 綁定標識 */
/* 從緩存池中取出Cell方塊視圖對象丽已,如果緩存池沒有,自動調(diào)用alloc/initWithFrame創(chuàng)建 */
- (UICollectionViewCell *)dequeueReusableCellWithReuseIdentifier:(NSString *)identifier
forIndexPath:(NSIndexPath *)indexPath;
/* kind參數(shù)設(shè)置 */
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;/* 綁定標識 */
/* 從緩存池中取出頂部視圖對象或者底部視圖對象,如果緩存池沒有嘁灯,自動調(diào)用alloc/initWithFrame創(chuàng)建 */
- (UICollectionReusableView *)dequeueReusableSupplementaryViewOfKind:(NSString *)kind
withReuseIdentifier:(NSString *)identifier
forIndexPath:(NSIndexPath *)indexPath;
UICollectionView的數(shù)據(jù)源方法
@required
/* 設(shè)置容器視圖各個組都有多少個Cell方塊 */
- (NSInteger)collectionView:(UICollectionView *)collectionView
numberOfItemsInSection:(NSInteger)section;
/* 設(shè)置Cell方塊視圖泻蚊,類似于UITableViewCell的設(shè)置 */
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath;
@optional
/* 容器視圖有多少個組,默認返回1 */
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView;
/* 設(shè)置頂部視圖和底部視圖旁仿,通過kind參數(shù)分辨是設(shè)置頂部還是底部 */
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView
viewForSupplementaryElementOfKind:(NSString *)kind
atIndexPath:(NSIndexPath *)indexPath;
UICollectionViewDelegate的常用方法
/* 選中Cell方塊時調(diào)用 */
- (void)collectionView:(UICollectionView *)collectionView
didSelectItemAtIndexPath:(NSIndexPath *)indexPath;
/* 取消選中Cell方塊時調(diào)用 */
- (void)collectionView:(UICollectionView *)collectionView
didDeselectItemAtIndexPath:(NSIndexPath *)indexPath;
我們使用更多的是UICollectionViewDelegate子協(xié)議UICollectionViewDelegateFlowLayout
該協(xié)議不僅包含父協(xié)議所有方法藕夫,還可以進行一些布局設(shè)置
UICollectionViewDelegateFlowLayout的常用布局方法
/* 設(shè)置每個方塊的尺寸大小 */
- (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;
/* 方塊視圖的緩存池標示 */
+ (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
{
//從緩存池中尋找方塊視圖對象办悟,如果沒有尘奏,該方法自動調(diào)用alloc/initWithFrame創(chuàng)建一個新的方塊視圖返回
LTCollectionViewCell *cell =
[collectionView dequeueReusableCellWithReuseIdentifier:[LTCollectionViewCell cellIdentifier]
forIndexPath:indexPath];
return cell;
? }
/* 注冊了方塊視圖后,當緩存池中沒有底部視圖的對象時候病蛉,自動調(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;
/* 頂部視圖的緩存池標示 */
+ (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
{
//從緩存池中尋找頂部視圖對象炫加,如果沒有,該方法自動調(diào)用alloc/initWithFrame創(chuàng)建一個新的頂部視圖返回
LTCollectionHeaderView *headerView =
[collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader
withReuseIdentifier:[LTCollectionHeaderView headerViewIdentifier]
forIndexPath:indexPath];
return headerView;
?}
/* 注冊了頂部視圖后铺然,當緩存池中沒有頂部視圖的對象時候俗孝,自動調(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;
/* 底部視圖的緩存池標示 */
+ (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
{
//從緩存池中尋找底部視圖對象,如果沒有魄健,該方法自動調(diào)用alloc/initWithFrame創(chuàng)建一個新的底部視圖返回
LTCollectionFooterView *footerView =
[collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter
withReuseIdentifier:[LTCollectionFooterView footerViewIdentifier]
forIndexPath:indexPath];
return footerView;
?}
/* 注冊了底部視圖后赋铝,當緩存池中沒有底部視圖的對象時候,自動調(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
下面是使用實例:
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è)置滾動方向為垂直滾動沽瘦,說明方塊是從左上到右下的布局排列方式
layout.scrollDirection = UICollectionViewScrollDirectionVertical;
//設(shè)置頂部視圖和底部視圖的大小革骨,當滾動方向為垂直時,設(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è)置背景,默認為黑色
//添加到主視圖
[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è)置容器中有多少個組 */
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
return 10;
?}
/* 設(shè)置每個組有多少個方塊 */
- (NSInteger)collectionView:(UICollectionView *)collectionView
numberOfItemsInSection:(NSInteger)section
{
return 20;
?}
/* 設(shè)置方塊的視圖 */
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
//獲取cell視圖助隧,內(nèi)部通過去緩存池中取筑凫,如果緩存池中沒有,就自動創(chuàng)建一個新的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è)置各個方塊的大小尺寸 */
- (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(@"點擊選擇了第%ld組第%ld個方塊",indexPath.section,indexPath.row);
?}
/* 方塊取消選中會調(diào)用 */
- (void)collectionView:(UICollectionView *)collectionView
didDeselectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"取消選擇第%ld組第%ld個方塊",indexPath.section,indexPath.row);
}
@end
效果圖如下并村,左邊為垂直滾動效果巍实,右邊為水平滾動效果
如果修改下布局代理方法的上下左右邊界距離:
/* 設(shè)置每一組的上下左右間距 */
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(0, 0, 0, 0);
}
LearnDemo里面的CollectionViewDemo