UICollectionView基础
- UICollectionViewFlowLayout:视图布局对象,继承自UICollectionViewLayout。
所有的视图布局对象都继承自UICollectionViewLayout。若我们要自定义布局对象,我们一般继承UICollectionViewFlowLayout就可以了。
- 需要实现三个协议;UICollectionViewDataSource(数据源)、UICollectionViewDelegateFlowLayout(视图布局)、UICollectionViewDelegate。
可以看得出,UICollectionView几乎和UITableView一样,但是视图布局和装饰视图让它更强大,UITableView能做到的UICollectionView都能做到,UICollectionView能做到的UITableView不一定能做到(这也是我一直选择UICollectionView的原因之一)。
UICollectionView实现步骤
- UICollectionView创建及注册
- UICollectionViewDataSource的实现
- UICollectionViewDelegateFlowLayout的实现(或者自定义UICollectionViewLayout实现)
- UICollectionViewDelegate的实现
熟悉UICollectionView的程序员都知道,实现过程很繁琐,数据源代理看的眼花缭乱,有思想的程序员也许都会在想同样的问题:
- 每次都要注册很烦,是不是内部可以根据某个标识判断是否注册及自动注册呢?
- 为什么内部不能根据我的数据计算几行几列,创建初始化视图及视图的大小,更高级的自动缓存高度呢?
- UICollectionViewDelegateFlowLayout的实现太麻烦了,要是可以不要写那么多该多好啊
我也一样是个有思想的码农(哈哈),一直在寻求可以同时解决这些痛处的方法,一次在和同学的聊天中,和同学聊到了数据即视图的思想,视图的布局都是由数据来驱动的,于是就有了 UICollectionView进阶第一步,(以下都是个人想法,不喜勿喷,有更好的想法可以联系我)
SuperCollectionView
- SuperCollectionView的结构
- SuperCollectionView的发动机(数据):(NSObject+XWReuseData)
@interface NSObject (XW)
/**
cell或者header,footer的高度,框架自动缓存
*/
@property (nonatomic, assign) CGFloat xw_height;
/**
cell或者header,footer的宽度,框架自动缓存
*/
@property (nonatomic, assign) CGFloat xw_width;
/**
cell或者header,footer的重用标识,框架自动缓存(可以为空,有默认值)
cell的重用标识(默认数据去除Data改为Cell)
header或者footer的重用标识 (默认数据去除Data改为View)
*/
@property (nonatomic, strong) NSString *reuseIdentifier;
/**
cell或者header,footer是否重用
*/
@property (nonatomic, assign) BOOL unReusable;
#pragma mark -
#pragma mark - 以下属性只对header或者footer生效
/**
collectionView每个section的内边距
*/
@property(nonatomic , assign) UIEdgeInsets cell_secionInset;
/**
collectionView每个section的边距
*/
@property(nonatomic , assign) CGFloat cell_minimumLineSpacing;
/**
collectionView每个item的边距
*/
@property(nonatomic , assign) CGFloat cell_minimumInteritemSpacing;
@end
数据驱动视图,一个个简单的数据可以拼凑出乎意料的页面,只有你想不到,没有SuperCollectionView做不到的
- SuperCollectionView注册:(UICollectionView+XWRegister)
@interface UICollectionView (XWRegister)
/**
* 注册列表缓存
*/
@property (nonatomic, strong) NSMutableArray *reuseIdentifierList;
-(UICollectionViewCell *)dequeueReusableCellWithIdentify:(NSString *)identify indexPath:(NSIndexPath *)indexPath reusable:(BOOL )reusable;
-(UICollectionReusableView *)dequeueReusableView:(NSString *)identify indexPath:(NSIndexPath *)indexPath kind:(NSString *)kind reusable:(BOOL )reusable;
@end
在XWCollectionViewDataSourceDelegate内完成了缓存重用标识并判断否注册及自动注册
- SuperCollectionView对外数据源接口协议
@protocol XWCollectionViewDataSource
@required
/**
* cell数据源(支持多个section返回值为二重数组即可)
*/
- (NSMutableArray *)cellDataListWithCollectionView:(UICollectionView *)collectionView;
@optional
/**
* 头部数据源
*/
- (NSMutableArray *)headerDataListWithCollectionView:(UICollectionView *)collectionView;
/**
* 尾部数据源
*/
- (NSMutableArray *)footerDataListWithCollectionView:(UICollectionView *)collectionView;
/**
* 每个secion对应的修饰背景view
*/
- (NSMutableArray *)decorationViewClassListWithCollectionView:(UICollectionView *)collectionView;
@end;
我对UICollectionView的数据源及UICollectionViewDelegateFlowLayout进行了高度封装(详细的见XWCollectionViewDataSourceDelegate),对代理进行了一层转发。
SuperCollectionView实战
看了上面的是不是更加感兴趣了(卧槽,还有这种操作),接下来就是见证奇迹的时刻,让我们一起来看看现在是如何使用UICollectionView的吧
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.cv];
// Do any additional setup after loading the view, typically from a nib.
}
#pragma mark - XWCollectionViewDataSource
-(NSMutableArray *)headerDataListWithCollectionView:(UICollectionView *)collectionView{
return self.headerDataList;
}
-(NSArray *)cellDataListWithCollectionView:(UICollectionView *)collectionView{
return [[NSMutableArray alloc] initWithObjects:self.cellDataList,self.cellDataList,self.cellDataList, nil];
}
-(NSMutableArray *)footerDataListWithCollectionView:(UICollectionView *)collectionView{
return self.footerDataList;
}
-(NSMutableArray *)decorationViewClassListWithCollectionView:(UICollectionView *)collectionView{
return self.decroationViewClassList;
}
#pragma mark - delegate
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
}
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
}
#pragma mark - getter
-(UICollectionView *)cv{
if (!_cv) {
_cv = [UICollectionView createWithFlowLayout];
_cv.frame = CGRectMake(0, 0, self.view.bounds.size.width, [UIScreen mainScreen].bounds.size.height);
_cv.backgroundColor = [UIColor whiteColor];
_cv.xw_dataSource = self;
_cv.xw_delegate = self;
}
return _cv;
}
-(NSMutableArray *)headerDataList{
if (!_headerDataList) {
_headerDataList = [NSMutableArray new];
[_headerDataList addObject:[ACollectionViewHeaderData new]];
[_headerDataList addObject:[ACollectionViewHeaderData new]];
NSObject * defaultData = [NSObject new];
defaultData.cell_width = 0.001;
defaultData.cell_height = 0.001;
defaultData.cell_minimumLineSpacing = 10;
defaultData.cell_minimumInteritemSpacing = 10;
defaultData.cell_secionInset = UIEdgeInsetsMake(10, 10, 10, 10);
[_headerDataList addObject:defaultData];
}
return _headerDataList;
}
-(NSMutableArray *)cellDataList{
if (!_cellDataList) {
_cellDataList = [NSMutableArray new];
ACollectionViewData * data = [ACollectionViewData new];
data.color = [UIColor redColor];
data.title = @"我是cell";
[_cellDataList addObject:data];
data = [ACollectionViewData new];
data.color = [UIColor blueColor];
data.title = @"我是cell";
[_cellDataList addObject:data];
data = [ACollectionViewData new];
data.color = [UIColor grayColor];
data.title = @"我是cell";
[_cellDataList addObject:data];
data = [ACollectionViewData new];
data.color = [UIColor cyanColor];
data.title = @"我是cell";
[_cellDataList addObject:data];
[_cellDataList addObject:data];
data = [ACollectionViewData new];
data.color = [UIColor blueColor];
data.title = @"我是cell";
[_cellDataList addObject:data];
}
return _cellDataList;
}
可以看出来data起到了很关键的作用,几个简单的data就可以驱动一个UICollectionView,这就是数据即视图,这样UICollectionView进阶之路走出了第一步,几行代码轻轻松松就可以搞定UICollectionView(我上我也行,哈哈)。如果你喜欢你也可以试试这样处理哦~
但这远远还不够,既然你能把数据源代理简化成这样,那你是不是能直接不写数据源代理呢,想想连数据源都不用写了,那是种什么体验啊,是的,没错,下一步要做的就是摒弃数据源(程序员:我不信,哈哈),敬请期待UICollectionView进阶之路(二)。
如果你觉得不错,可以加入群639762230一起探讨哦~