游小龙的技术博客点击阅读更多
1 UICollectionView的前世今生
UICollectionView在iOS6(2012年6提出的)中首次被提出(现在已经是iOS9),它和UITableView共享API设计,在上面做了一些灵活扩展。UICollectionViewDataSource(数据源)、UICollectionViewDelegateFlowLayout(视图布局)、UICollectionViewDelegate。
UICollectionViewFlowLayout:视图布局对象(流视图:一行排满,自动排到下行),继承自UICollectionViewLayout。
2 UICollectionView的布局
UICollectionView是由UICollectionViewDelegateFlowLayout(视图布局)UICollectionViewDataSource(数据源)UICollectionViewDelegate这三个驱动的。
他们为其显示的子视图集扮演为愚蠢的容器(dumb containers),对他们真实的内容(contents)毫不知情。
2.1UICollectionViewLayout
UICollectionView进一步抽象了。它将其子视图的位置,大小和外观的控制权委托给一个单独的布局对象。通过提供一个自定义布局对象,你几乎可以实现任何你能想象到的布局。布局继承自UICollectionViewLayout这个抽象基类。
一下是在UICollectionViewLayout终须实现的3个类
**
2.1.1—–返回对应于indexPath的位置的cell的布局属性 获取某个indexPath下cell的LayoutAttributes信息—–
**
(UICollectionViewLayoutAttributes*)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
**
2.1.2—-获取在某个区域内(以contentSize为依据)可见cell的Attributes信息,这个函数需要获取这个可见区域内的indexPath的范围,而获取indexPath范围的方法需要获取某个点上cell的indexPath的方法,而这个方法又依赖于每个cell的size。—–
**
-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect
2.1.3—-计算整个UICollectionView的contentSize,如果计算的大了,有可能会引起crash(具体情况取决于超出的尺寸是否会导致新的cell出现)—–
**
-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect
手写我们的第一个UICollectionView
1.创建UICollectionView视图
先在.h文件设置属性 代理(这个够细致了哈 )
#import <UIKit/UIKit.h>
@interface View2 : UIViewController<UICollectionViewDelegate,UICollectionViewDataSource,UIScrollViewDelegate>
//这里之前写了weak 一直显示不了 坑我啊 啊哈啊啊啊啊啊
//@property (weak,nonatomic) UICollectionView *collectionView;
@property (nonatomic,strong) UICollectionView *collectionView;
@property (nonatomic,strong) UIButton *btn2;
@end
- (void)loadCollectionView
{
//1.定义布局对象
self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0.0f, 200.0f, width, height) collectionViewLayout:[[CircleLayout alloc] init]];
//【CircleLayout这个是布局对象类继承UICollectionViewLayout】
//2.注册cell(sectionHeader、sectionFooter 这两个表头 跟表尾 不一定要实现)
[self.collectionView registerClass:[ShowImageCell class] forCellWithReuseIdentifier:cellId];
//【ShowImageCell这个是我们要实现的单元格cell】
//3.设置代理
self.collectionView.delegate = self;
self.collectionView.dataSource = self;
//一些其他处理的设置 非必要
self.collectionView.backgroundColor = [UIColor grayColor];
[self.collectionView setContentOffset:CGPointMake(width, 0.0F)];
[self.view addSubview:self.collectionView];
#import "View2.h"
//照片显示的类 collectionview
#import "CircleLayout.h"
#import "ShowImageCell.h"
//看这里
-----定义一个字符串来保存 单元格
方法一
#define cellId @"cellId"
#define headerId @"headerId"
#define footerId @"footerId"
方法二
// 注意const的位置
//static NSString *const KCellId = @"cellId";
//static NSString *const headerId = @"headerId";
//static NSString *const footerId = @"footerId";
@interface View2 ()
2.实现UICollectionViewDataSource的几个代理方法
#pragma mark - UICollectionViewDelegate
#pragma mark - UICollectionViewDataSource
//1.设置分区的个数
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
//2.设置返回的行数
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return 10;
}
##这个是重点哈 ##
//3.设置cell的样式
- (UICollectionViewCell *)collectionView:(UICollectionView *)cView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
//步骤1 设置重用的单元格 设重用表示符
ShowImageCell *cell = (ShowImageCell *)[cView dequeueReusableCellWithReuseIdentifier:CellId
forIndexPath:indexPath];
if (!cell) {
NSLog(@"不是吧 cell为nil");
return nil;
}
//步骤2 根据需要填写 cell显示格式(我这里是文字跟图片)
NSString *imageName = [NSString stringWithFormat:@"%d.JPG",indexPath.row];
cell.imageView.image = [UIImage imageNamed:imageName];
cell.titleLabel.text = imageName;
//步骤3 好吧 这一步 一个单元格重用就创建好了
return cell;
}
//还有一些其他代理根据需要 添加方法这里在多写一个 表头跟表尾
--------------------------------下面的可以不看了
// 和UITableView类似,UICollectionView也可设置段头段尾
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
if([kind isEqualToString:UICollectionElementKindSectionHeader])
{
UICollectionReusableView *headerView = [_collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:headerId forIndexPath:indexPath];
if(headerView == nil)
{
headerView = [[UICollectionReusableView alloc] init];
}
headerView.backgroundColor = [UIColor grayColor];
return headerView;
}
else if([kind isEqualToString:UICollectionElementKindSectionFooter])
{
UICollectionReusableView *footerView = [_collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:footerId forIndexPath:indexPath];
if(footerView == nil)
{
footerView = [[UICollectionReusableView alloc] init];
}
footerView.backgroundColor = [UIColor lightGrayColor];
return footerView;
}
return nil;
}
3.接下来我们实现布局
3.1新建一个类 继承 UICollectionViewLayout
//.h文件
#import <UIKit/UIKit.h>
@interface CircleLayout : UICollectionViewLayout
@end
3.2在.m文件中实现3个必要方法 前面有提到哈
#import "CircleLayout.h"
//这个类就控制布局的
@implementation CircleLayout
//一
-(CGSize)collectionViewContentSize
{
return size;
}
//二
#pragma mark - UICollectionViewLayout
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
return attributes;
}
//三
-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect
{
return attributes;
}
@end
4.最后创建单元格 继承自UICollectionViewCell
步骤一:继承 属性
#import <UIKit/UIKit.h>
@interface ShowImageCell : UICollectionViewCell
//这里写属性 单元格显示的信息
@property (nonatomic,strong) UIImageView *imageView;
@property (nonatomic,strong) UILabel *titleLabel;
@end
步骤二:方法重写 实现
#import "ShowImageCell.h"
@implementation ShowImageCell
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
_imageView = [[UIImageView alloc] init];
[self.contentView addSubview:_imageView];
_titleLabel = [[UILabel alloc] init];
_titleLabel.textColor = [UIColor whiteColor];
[self.contentView addSubview:_titleLabel];
}
return self;
}
//这是写在实现这里面的 不去调用也能实现
-(void)layoutSubviews{
_imageView.frame = self.contentView.bounds;
_titleLabel.frame = CGRectMake(0.0f,0.0f , self.contentView.bounds.size.width, 44.0f);
}
@end