UICollectionView简介
NS_CLASS_AVAILABLE_IOS(6_0) @interface UICollectionView : UIScrollView
打开UICollectionView的.h文件可以发现,UIcollectionView自iOS6以后加入UIKit框架的,它跟UITableView一样继承自UIScrollView。所以在目前市场上所有版本的iPhone上,基本都能支持使用UICollectionView。而且在对数据的展示和UI的构建上,UICollectionView也甩出UITableView十八条街。
UICollectionView的实现说简单挺简单的,无非也就是两个代理和数据源的配合,比UITableView略微复杂的就是有一个需要继承自UICollectionViewLayout的布局信息。
但是说复杂也能很复杂,包括整个UICollectionView的定制布局(瀑布流等)和布局动画以及插入删除item时的动画,也是一个值得深究的控件。
本章主要是简略的实现一个有头视图、尾视图和展示视图的纵向UICollectionView。更为复杂的定制布局我们会在以后的章节详细展开。
1.先说说 Layout
NS_CLASS_AVAILABLE_IOS(6_0) @interface UICollectionViewLayout : NSObject <NSCoding>
所有关于UICollectionView的精髓,几乎都在这个类上面,它基本确定了整个UICollectionView的布局信息甚至包括一些动画效果,但是定制它是一个问题,而且它是一个抽像类,不能直接被使用,需要定义一个继承自它的子类,然后来徐徐展开。
但是Apple官方给我们已经定制好了一个类 : UICollectionViewFlowLayout
,这个类继承自UICollectionViewLayout
,并且定制好了代理方法来方便我们控制UICollectionView的布局,但是也仅仅限制于网格布局。
下面我们就是用UICollectionViewFlowLayout
来写我们的简易UICollectionView Demo。
2.代码开撸
2.1 先写基本代码,兵马未动粮草先行,我们先构建一个模拟的数据源数组,再创建一个UICollectionView,关联上UICollectionViewFlowLayout的对象,设置代理,注册好Cell和Header、Footer的信息。
//数据源
-(NSArray *)dataArray
{
if (!_dataArray) {
_dataArray = [[NSArray alloc] init];
NSMutableArray * theArray = [NSMutableArray array];
for (NSInteger index = 0; index < 3; index++) {
NSMutableArray * subArray = [NSMutableArray array];
for (NSInteger indexJ = 0; indexJ < 10; indexJ++) {
MainModel * model = [MainModel new];
model.indexStr = [NSString stringWithFormat:@"%ld-%ld",index,indexJ];
[subArray addObject:model];
}
[theArray addObject:[NSArray arrayWithArray:subArray]];
}
_dataArray = [NSArray arrayWithArray:theArray];
}
return _dataArray;
}
//UICollectionView视图
-(UICollectionView *)mainCollectionView
{
if (!_mainCollectionView) {
UICollectionViewFlowLayout * layout = [UICollectionViewFlowLayout new];
layout.scrollDirection = UICollectionViewScrollDirectionVertical;
layout.sectionHeadersPinToVisibleBounds = NO;//头部视图悬停设为YES
layout.sectionFootersPinToVisibleBounds = NO;//尾部视图悬停设为YES
_mainCollectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout];
_mainCollectionView.backgroundColor = [UIColor whiteColor];
_mainCollectionView.delegate = self;
_mainCollectionView.dataSource = self;
[_mainCollectionView registerClass:[MainCollectionViewCell class] forCellWithReuseIdentifier:[MainCollectionViewCell reuseIdentifier]];
[_mainCollectionView registerClass:[MainCollectionHeaderView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:[MainCollectionHeaderView reuseIdentifier]];
[_mainCollectionView registerClass:[MainCollectionFooterView class] forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:[MainCollectionFooterView reuseIdentifier]];
}
return _mainCollectionView;
}
2.2 然后我们添加代理,这里我们通过代理的方式控制布局,这样更易于我们的操控。
UICollectionViewDelegate:主要管理于用户交互方面
UICollectionViewDataSource:主要管理视图数据源方面
UICollectionViewDelegateFlowLayout:主要管理布局信息方面
@interface ViewController ()<UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout>
UICollectionView Data Source methods (代理里面还有许多方法,我们主要展示最关键的几个)
//返回多少个组
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return self.dataArray.count;
}
//返回每组多少个视图
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
NSArray * subArray = self.dataArray[section];
return subArray.count;
}
//返回视图的具体事例,我们的数据关联就是放在这里
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
MainCollectionViewCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:[MainCollectionViewCell reuseIdentifier] forIndexPath:indexPath];
cell.backgroundColor = [UIColor orangeColor];
cell.contentView.frame = cell.bounds;
cell.backgroundColor = [UIColor lightGrayColor];
MainModel * model = self.dataArray[indexPath.section][indexPath.row];
cell.title = model.indexStr;
return cell;
}
UICollectionView Delegate method (代理里面还有许多方法,我们主要展示最关键的几个)
//选中某个 item 触发
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"选中 : %ld--%ld",indexPath.section,indexPath.item);
}
//取消某个 item 触发
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"取消选中 : %ld--%ld",indexPath.section,indexPath.item);
}
UICollectionView Delegate FlowLayout method (代理里面还有许多方法,我们主要展示最关键的几个)
// cell 尺寸
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake((self.view.bounds.size.width-5-5-10*2)/3.0, 50);
}
// 装载内容 cell 的内边距
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(5, 5, 5, 5);
}
//最小行间距
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
return 10.0f;
}
//item最小间距
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
{
return 10.0f;
}
//头视图尺寸
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
{
return CGSizeMake(self.view.bounds.size.width, 50);
}
//尾视图尺寸
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section
{
return CGSizeMake(self.view.bounds.size.width, 50);
}
2.3 最后是我们的实现效果:
上图是纵向效果,如果需要横向,则改一下UICollectionViewFlowLayout
的scrollDirection
属性即可,当然啦,尺寸各方面需要再细细调节,简单的很,就需要各位看官慢慢探索了。