UICollectionView基礎(chǔ)
- UICollectionViewFlowLayout:視圖布局對象钢坦,繼承自UICollectionViewLayout究孕。
所有的視圖布局對象都繼承自UICollectionViewLayout啥酱。若我們要自定義布局對象爹凹,我們一般繼承UICollectionViewFlowLayout就可以了。
- 需要實現(xiàn)三個協(xié)議镶殷;UICollectionViewDataSource(數(shù)據(jù)源)禾酱、UICollectionViewDelegateFlowLayout(視圖布局)、UICollectionViewDelegate绘趋。
可以看得出颤陶,UICollectionView幾乎和UITableView一樣,但是視圖布局和裝飾視圖讓它更強大陷遮,UITableView能做到的UICollectionView都能做到滓走,UICollectionView能做到的UITableView不一定能做到(這也是我一直選擇UICollectionView的原因之一)。
UICollectionView實現(xiàn)步驟
- UICollectionView創(chuàng)建及注冊
- UICollectionViewDataSource的實現(xiàn)
- UICollectionViewDelegateFlowLayout的實現(xiàn)(或者自定義UICollectionViewLayout實現(xiàn))
- UICollectionViewDelegate的實現(xiàn)
熟悉UICollectionView的程序員都知道帽馋,實現(xiàn)過程很繁瑣搅方,數(shù)據(jù)源代理看的眼花繚亂,有思想的程序員也許都會在想同樣的問題:
- 每次都要注冊很煩绽族,是不是內(nèi)部可以根據(jù)某個標(biāo)識判斷是否注冊及自動注冊呢姨涡?
- 為什么內(nèi)部不能根據(jù)我的數(shù)據(jù)計算幾行幾列,創(chuàng)建初始化視圖及視圖的大小吧慢,更高級的自動緩存高度呢涛漂?
- UICollectionViewDelegateFlowLayout的實現(xiàn)太麻煩了,要是可以不要寫那么多該多好啊
我也一樣是個有思想的碼農(nóng)(哈哈)检诗,一直在尋求可以同時解決這些痛處的方法匈仗,一次在和同學(xué)的聊天中,和同學(xué)聊到了數(shù)據(jù)即視圖的思想逢慌,視圖的布局都是由數(shù)據(jù)來驅(qū)動的悠轩,于是就有了 UICollectionView進(jìn)階第一步,(以下都是個人想法涕癣,不喜勿噴哗蜈,有更好的想法可以聯(lián)系我)
SuperCollectionView
- SuperCollectionView的結(jié)構(gòu)
- SuperCollectionView的發(fā)動機(數(shù)據(jù)):(NSObject+XWReuseData)
@interface NSObject (XW)
/**
cell或者h(yuǎn)eader,footer的高度,框架自動緩存
*/
@property (nonatomic, assign) CGFloat xw_height;
/**
cell或者h(yuǎn)eader,footer的寬度坠韩,框架自動緩存
*/
@property (nonatomic, assign) CGFloat xw_width;
/**
cell或者h(yuǎn)eader,footer的重用標(biāo)識距潘,框架自動緩存(可以為空,有默認(rèn)值)
cell的重用標(biāo)識(默認(rèn)數(shù)據(jù)去除Data改為Cell)
header或者footer的重用標(biāo)識 (默認(rèn)數(shù)據(jù)去除Data改為View)
*/
@property (nonatomic, strong) NSString *reuseIdentifier;
/**
cell或者h(yuǎn)eader,footer是否重用
*/
@property (nonatomic, assign) BOOL unReusable;
#pragma mark -
#pragma mark - 以下屬性只對header或者footer生效
/**
collectionView每個section的內(nèi)邊距
*/
@property(nonatomic , assign) UIEdgeInsets cell_secionInset;
/**
collectionView每個section的邊距
*/
@property(nonatomic , assign) CGFloat cell_minimumLineSpacing;
/**
collectionView每個item的邊距
*/
@property(nonatomic , assign) CGFloat cell_minimumInteritemSpacing;
@end
數(shù)據(jù)驅(qū)動視圖只搁,一個個簡單的數(shù)據(jù)可以拼湊出乎意料的頁面音比,只有你想不到,沒有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內(nèi)完成了緩存重用標(biāo)識并判斷否注冊及自動注冊
- SuperCollectionView對外數(shù)據(jù)源接口協(xié)議
@protocol XWCollectionViewDataSource <NSObject>
@required
/**
* cell數(shù)據(jù)源(支持多個section返回值為二重數(shù)組即可)
*/
- (NSMutableArray *)cellDataListWithCollectionView:(UICollectionView *)collectionView;
@optional
/**
* 頭部數(shù)據(jù)源
*/
- (NSMutableArray *)headerDataListWithCollectionView:(UICollectionView *)collectionView;
/**
* 尾部數(shù)據(jù)源
*/
- (NSMutableArray *)footerDataListWithCollectionView:(UICollectionView *)collectionView;
/**
* 每個secion對應(yīng)的修飾背景view
*/
- (NSMutableArray<Class> *)decorationViewClassListWithCollectionView:(UICollectionView *)collectionView;
@end;
我對UICollectionView的數(shù)據(jù)源及UICollectionViewDelegateFlowLayout進(jìn)行了高度封裝(詳細(xì)的見XWCollectionViewDataSourceDelegate)氢惋,對代理進(jìn)行了一層轉(zhuǎn)發(fā)洞翩。
SuperCollectionView實戰(zhàn)
看了上面的是不是更加感興趣了(臥槽稽犁,還有這種操作),接下來就是見證奇跡的時刻骚亿,讓我們一起來看看現(xiàn)在是如何使用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<Class> *)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起到了很關(guān)鍵的作用已亥,幾個簡單的data就可以驅(qū)動一個UICollectionView,這就是數(shù)據(jù)即視圖来屠,這樣UICollectionView進(jìn)階之路走出了第一步虑椎,幾行代碼輕輕松松就可以搞定UICollectionView(我上我也行,哈哈)俱笛。如果你喜歡你也可以試試這樣處理哦~
但這遠(yuǎn)遠(yuǎn)還不夠捆姜,既然你能把數(shù)據(jù)源代理簡化成這樣,那你是不是能直接不寫數(shù)據(jù)源代理呢迎膜,想想連數(shù)據(jù)源都不用寫了泥技,那是種什么體驗啊,是的磕仅,沒錯珊豹,下一步要做的就是摒棄數(shù)據(jù)源(程序員:我不信,哈哈)宽涌,敬請期待UICollectionView進(jìn)階之路(二)平夜。
GitHub: https://github.com/WangJianShi/UICollectionView-Widget