collection控件用来实现界面的各种自定义布局,最常用其作为横向、竖向的布局控件。很早之前,系统对于collection的支持并不是很好。所以自己实现了支持自定义布局、自定义cell的collection控件。自定义的collection可以满足所有的产品特殊需求及动态效果,例如在某些特殊情况下可能需要除选中cell之外的其它cell执行布局动画等。在collection的基础之上,我又实现了支持cell拖动、拖离窗体的tabview控件。本文主要介绍自定义collection的设计与实现,后续持续更新多tab的tabview控件。
我有几张阿里云幸运券分享给你,用券购买或者升级阿里云相应产品会有特惠惊喜哦!把想要买的产品的幸运券都领走吧!快下手,马上就要抢光了。
产品中的一些实现效果
mac旺旺表情面板,实现grid与横向布局
mac千牛工作台用作横向布局
ios千牛历史登录页面实现当前选中cell变大并且选中cell总中最中位置校准动效的效果
collection
collection主要包括:继承scrollview的collectionview,数据源协议collectionviewdatasource,事件响应协议collectoinviewdelegate,布局基类collectoinlayout以及展示单元collectioncellview。
模块图如下:
collectionview
collection容器包含指实现collectionviewdatasource、collectoinviewdelegate协议的指针以及collectoinlayout成员,同时维护collectoincellview的控件重用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
@interface wwcollectionview : nsscrollview // 布局对象 @property (retain) wwcollectionviewlayout *layout; // 数据源 @property (weak) id datasource; // 事件响应 @property (weak) id delegate; // 重加载数据 ( void )reloaddata; // 重排布 ( void )invalidatelayout; // 取消返回选中 ( void )unselectedall; // 注册重用对象 ( void )registerclass:( class )cellclass forcellwithreuseidentifier:(nsstring *)identifier; // 对象重用 (id)dequeuereusablecellwithreuseidentifier:(nsstring )identifier forindexpath:(nsindexpath )indexpath; // 设置选中对象 ( void )selectitematindexpath:(nsindexpath *)indexpath animated:( bool )animated; // 当前选中对象 (nsindexpath *)selecteditem; // 重加载indexpath item ( void )reloaditemsatindexpath:(nsindexpath *)indexpath; // 插入 ( void )insertitemsatindexpath:(nsindexpath *)indexpath withanimate:( bool )animate; // 删除 ( void )deleteitemsatindexpath:(nsindexpath *)indexpath withanimate:( bool )animate; // 重新排列 ( void )relayoutwithanimation:( bool )animated completion:( void (^)( bool finished))completion; // 滚动到apoint ( void )scrolltopoint:(nspoint)apoint withanimate:( bool )animate; @end |
collectionviewdatasource
collection展示的数据源,由宿主实现。
1
2
3
4
5
6
7
8
|
@protocol wwcollectionviewdatasource // 返回indexpath下标的cell (wwcollectioncellview )collectview:(wwcollectionview )collectionview cellforitematindexpath:(nsindexpath *)indexpath; // 总cell个数 (nsinteger)numberofitemincollectionview:(wwcollectionview *)collectionview; // cell的数据 (id)collectionview:(wwcollectionview )colletionview objectvalueatindexpath:(nsindexpath )indexpath; @end |
collectoinviewdelegate
collection事件的回调响应,由宿主实现。
1
2
3
4
5
6
|
@protocol wwcollectionviewdelegate // indexpath元素被选中 ( void )collectionview:(wwcollectionview )collectionview didselectitematindexpath:(nsindexpath )indexpath; // 是否支持选中 ( bool )collectionview:(wwcollectionview )collectionview shouldselectitemsatindexpaths:(nsindexpath )indexpath; @end |
collectoinlayout
collectioncellview的布局方案。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
@interface wwcollectionviewlayout : nsobject // 布局基类 @property (weak) wwcollectionview *collectionview; // 每个cell元素大小 @property (assign) nssize itemsize; // edgeinsets @property (assign) nsedgeinsets edgeinsets; // scrollview使用,表示整个画布大小 @property (assign) nssize viewcontentsize; (instancetype)initwithcollectionview:(wwcollectionview *)collectionview; ( void )invalidatelayout; // 返回index的cell大小 (nsrect)frameforindexpath:(nsindexpath *)index total:(nsinteger)total; (nssize)collectionviewcontentsize; @end // 横向布局控件 @interface wwflowcollectionviewlayout : wwcollectionviewlayout @property (assign) cgfloat headmargin; @property (assign) cgfloat tailmargin; @end // grid布局控件 @interface wwgridcollectionviewlayout : wwcollectionviewlayout // 每行多少个 @property (assign) nsinteger numberperrow; @property (assign) cgfloat headmargin; @property (assign) cgfloat tailmargin; @end |
1
|
@implementation wwflowcollectionviewlayout |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
( void )invalidatelayout { nsinteger cellcount = [self.collectionview.datasource numberofitemincollectionview:self.collectionview]; cgrect bounds = self.collectionview.bounds; // 画布宽度 cgfloat width = _headmargin + _tailmargin + (cellcount - 1) (self.edgeinsets.left + self.edgeinsets.right) + self.itemsize.width cellcount; if (width < bounds.size.width) { width = bounds.size.width; } self.viewcontentsize = nsmakesize(width, bounds.size.height); [super invalidatelayout]; } (nsrect)frameforindexpath:(nsindexpath *)index total:(nsinteger)total { cgfloat leftpos = self.headmargin + [index indexatposition:0] * (self.itemsize.width + self.edgeinsets.left + self.edgeinsets.right); // 返回cell的rect return nsmakerect(leftpos, self.edgeinsets.top, self.itemsize.width, self.itemsize.height); } @end |
collectoincellview
collection展示的cell控件。
1
2
3
4
5
6
7
8
|
@interface wwcollectioncellview : nsview // 当前cell被选中 @property (nonatomic, assign) bool selected; // 数据 @property (nonatomic, retain) id datavalue; // 使用前重置展示效果 ( void )reset; @end |
原文链接:http://blog.csdn.net/qq_36510261/article/details/78741030