iOS开发UI篇—自定义瀑布流控件(cell的事件处理)
2014-12-30 18:30
627 查看
iOS开发UI篇—自定义瀑布流控件(cell的事件处理)
一、关于cell的复用的补充
在设置每个索引位置对应的cell的方法中,打印cell的索引和地址,已查看cell的循环利用情况
查看:
![](http://images.cnitblog.com/i/450136/201407/301110473218207.png)
二、事件处理
1.在cell创建的时候添加一个label,设置label的tag值,以便在之后能够获取到label。
代码示例:
YYViewController.m文件
2.在YYWaterflowView.m中,监听手指对瀑布流的触碰,获得手指在屏幕上点击的触摸点,判断该触摸点是否在cell上,在哪个cell上?
如果点击了cell调用代理方法,那么处理对应cell的点击事件。
YYWaterflowView.m文件
实现效果:
![](http://images.cnitblog.com/i/450136/201407/301117481965994.png)
点击对应的cell,能够监听并对点击事件进行处理。
![](http://images.cnitblog.com/i/450136/201407/301118422124224.png)
三、补充说明
示例代码:
![](http://images.cnitblog.com/i/450136/201407/301122243213203.png)
说明:
touch.view指的是子控件(单个cell)以这个cell的左上角为(0,0)进行坐标计算
self指的是整个瀑布流,以整个瀑布流的左上角为(0,0)进行坐标计算
打印查看:
一、关于cell的复用的补充
在设置每个索引位置对应的cell的方法中,打印cell的索引和地址,已查看cell的循环利用情况
1 -(YYWaterflowViewCell *)waterflowView:(YYWaterflowView *)waterflowView cellAtIndex:(NSUInteger)index 2 { 3 // YYWaterflowViewCell *cell=[[YYWaterflowViewCell alloc]init]; 4 5 static NSString *ID=@"cell"; 6 YYWaterflowViewCell *cell=[waterflowView dequeueReusableCellWithIdentifier:ID]; 7 if (cell==nil) { 8 cell=[[YYWaterflowViewCell alloc]init]; 9 cell.identifier=ID; 10 //给cell设置一个随机色 11 cell.backgroundColor=YYRandomColor; 12 // [cell addSubview:[UIButton buttonWithType:UIButtonTypeContactAdd]]; 13 } 14 //通过取出cell中的label,重新为label的text赋值 15 16 NSLog(@"%d---%p",index,cell); 17 return cell; 18 }
查看:
![](http://images.cnitblog.com/i/450136/201407/301110473218207.png)
二、事件处理
1.在cell创建的时候添加一个label,设置label的tag值,以便在之后能够获取到label。
代码示例:
YYViewController.m文件
1 // YYViewController.m 2 // 06-瀑布流 3 // 4 // Created by apple on 14-7-28. 5 // Copyright (c) 2014年 wendingding. All rights reserved. 6 // 7 8 #import "YYViewController.h" 9 #import "YYWaterflowView.h" 10 #import "YYWaterflowViewCell.h" 11 12 @interface YYViewController ()<YYWaterflowViewDelegate,YYWaterflowViewDataSource> 13 14 @end 15 16 @implementation YYViewController 17 18 - (void)viewDidLoad 19 { 20 [super viewDidLoad]; 21 YYWaterflowView *waterflow=[[YYWaterflowView alloc]init]; 22 waterflow.frame=self.view.bounds; 23 waterflow.delegate=self; 24 waterflow.dadaSource=self; 25 [self.view addSubview:waterflow]; 26 27 //刷新数据 28 [waterflow reloadData]; 29 } 30 31 #pragma mark-数据源方法 32 -(NSUInteger)numberOfCellsInWaterflowView:(YYWaterflowView *)waterflowView 33 { 34 return 40; 35 } 36 -(NSUInteger)numberOfColumnsInWaterflowView:(YYWaterflowView *)waterflowView 37 { 38 return 3; 39 } 40 -(YYWaterflowViewCell *)waterflowView:(YYWaterflowView *)waterflowView cellAtIndex:(NSUInteger)index 41 { 42 // YYWaterflowViewCell *cell=[[YYWaterflowViewCell alloc]init]; 43 44 static NSString *ID=@"cell"; 45 YYWaterflowViewCell *cell=[waterflowView dequeueReusableCellWithIdentifier:ID]; 46 if (cell==nil) { 47 cell=[[YYWaterflowViewCell alloc]init]; 48 cell.identifier=ID; 49 //给cell设置一个随机色 50 cell.backgroundColor=YYRandomColor; 51 // [cell addSubview:[UIButton buttonWithType:UIButtonTypeContactAdd]]; 52 //在cell中添加一个label,设置tag值 53 UILabel *label=[[UILabel alloc]init]; 54 label.tag=10; 55 //注意:需要设置控件的frame值,否则不会显示 56 label.frame=CGRectMake(0, 0, 20, 20); 57 [cell addSubview:label]; 58 } 59 //通过取出cell中的label,重新为label的text赋值 60 UILabel *label=(UILabel *)[cell viewWithTag:10]; 61 label.text=[NSString stringWithFormat:@"%d",index]; 62 63 NSLog(@"%d---%p",index,cell); 64 return cell; 65 } 66 67 68 #pragma mark-代理方法 69 -(CGFloat)waterflowView:(YYWaterflowView *)waterflowView heightAtIndex:(NSUInteger)index 70 { 71 switch (index%3) { 72 case 0:return 90; 73 case 1:return 110; 74 case 2:return 80; 75 default:return 120; 76 } 77 } 78 -(CGFloat)waterflowView:(YYWaterflowView *)waterflowView marginForType:(YYWaterflowViewMarginType)type 79 { 80 switch (type) { 81 case YYWaterflowViewMarginTypeTop: 82 case YYWaterflowViewMarginTypeBottom: 83 case YYWaterflowViewMarginTypeLeft: 84 case YYWaterflowViewMarginTypeRight: 85 return 10; 86 case YYWaterflowViewMarginTypeColumn: 87 case YYWaterflowViewMarginTypeRow: 88 return 5; 89 } 90 } 91 -(void)waterflowView:(YYWaterflowView *)waterflowView didSelectAtIndex:(NSUInteger)index 92 { 93 NSLog(@"点击了第%d个cell",index); 94 } 95 @end
2.在YYWaterflowView.m中,监听手指对瀑布流的触碰,获得手指在屏幕上点击的触摸点,判断该触摸点是否在cell上,在哪个cell上?
如果点击了cell调用代理方法,那么处理对应cell的点击事件。
YYWaterflowView.m文件
1 // 2 // YYWaterflowView.m 3 // 06-瀑布流 4 // 5 // Created by apple on 14-7-29. 6 // Copyright (c) 2014年 wendingding. All rights reserved. 7 // 8 9 #import "YYWaterflowView.h" 10 #import "YYWaterflowViewCell.h" 11 #define YYWaterflowViewDefaultNumberOfClunms 3 12 #define YYWaterflowViewDefaultCellH 100 13 #define YYWaterflowViewDefaultMargin 10 14 15 @interface YYWaterflowView() 16 /** 17 * 所有cell的frame数据 18 */ 19 @property(nonatomic,strong)NSMutableArray *cellFrames; 20 /** 21 * 正在展示的cell 22 */ 23 @property(nonatomic,strong)NSMutableDictionary *displayingCells; 24 /** 25 * 缓存池(使用SET) 26 */ 27 @property(nonatomic,strong)NSMutableSet *reusableCells; 28 @end 29 30 @implementation YYWaterflowView 31 32 #pragma mark-懒加载 33 -(NSMutableArray *)cellFrames 34 { 35 if (_cellFrames==nil) { 36 _cellFrames=[NSMutableArray array]; 37 } 38 return _cellFrames; 39 } 40 41 -(NSMutableDictionary *)displayingCells 42 { 43 if (_displayingCells==nil) { 44 _displayingCells=[NSMutableDictionary dictionary]; 45 } 46 return _displayingCells; 47 } 48 49 -(NSMutableSet *)reusableCells 50 { 51 if (_reusableCells==nil) { 52 _reusableCells=[NSMutableSet set]; 53 } 54 return _reusableCells; 55 } 56 57 - (id)initWithFrame:(CGRect)frame 58 { 59 self = [super initWithFrame:frame]; 60 if (self) { 61 } 62 return self; 63 } 64 65 #pragma mark-公共方法 66 /** 67 * 刷新数据 68 * 1.计算每个cell的frame 69 */ 70 -(void)reloadData 71 { 72 //cell的总数是多少 73 int numberOfCells=[self.dadaSource numberOfCellsInWaterflowView:self]; 74 75 //cell的列数 76 int numberOfColumns=[self numberOfColumns]; 77 78 //间距 79 CGFloat leftM=[self marginForType:YYWaterflowViewMarginTypeLeft]; 80 CGFloat rightM=[self marginForType:YYWaterflowViewMarginTypeRight]; 81 CGFloat columnM=[self marginForType:YYWaterflowViewMarginTypeColumn]; 82 CGFloat topM=[self marginForType:YYWaterflowViewMarginTypeTop]; 83 CGFloat rowM=[self marginForType:YYWaterflowViewMarginTypeRow]; 84 CGFloat bottomM=[self marginForType:YYWaterflowViewMarginTypeBottom]; 85 86 //(1)cell的宽度 87 //cell的宽度=(整个view的宽度-左边的间距-右边的间距-(列数-1)X每列之间的间距)/总列数 88 CGFloat cellW=(self.frame.size.width-leftM-rightM-(numberOfColumns-1)*columnM)/numberOfColumns; 89 90 91 92 //用一个C语言的数组来存放所有列的最大的Y值 93 CGFloat maxYOfColumns[numberOfColumns]; 94 for (int i=0; i<numberOfColumns; i++) { 95 //初始化数组的数值全部为0 96 maxYOfColumns[i]=0.0; 97 } 98 99 100 //计算每个cell的fram 101 for (int i=0; i<numberOfCells; i++) { 102 103 //(2)cell的高度 104 //询问代理i位置的高度 105 CGFloat cellH=[self heightAtIndex:i]; 106 107 //cell处在第几列(最短的一列) 108 NSUInteger cellAtColumn=0; 109 110 //cell所处那列的最大的Y值(当前最短的那一列的最大的Y值) 111 //默认设置最短的一列为第一列(优化性能) 112 CGFloat maxYOfCellAtColumn=maxYOfColumns[cellAtColumn]; 113 114 //求出最短的那一列 115 for (int j=0; j<numberOfColumns; j++) { 116 if (maxYOfColumns[j]<maxYOfCellAtColumn) { 117 cellAtColumn=j; 118 maxYOfCellAtColumn=maxYOfColumns[j]; 119 } 120 } 121 122 //(3)cell的位置(X,Y) 123 //cell的X=左边的间距+列号*(cell的宽度+每列之间的间距) 124 CGFloat cellX=leftM+cellAtColumn*(cellW +columnM); 125 //cell的Y,先设定为0 126 CGFloat cellY=0; 127 if (maxYOfCellAtColumn==0.0) {//首行 128 cellY=topM; 129 }else 130 { 131 cellY=maxYOfCellAtColumn+rowM; 132 } 133 134 //设置cell的frame并添加到数组中 135 CGRect cellFrame=CGRectMake(cellX, cellY, cellW, cellH); 136 [self.cellFrames addObject:[NSValue valueWithCGRect:cellFrame]]; 137 138 //更新最短那一列的最大的Y值 139 maxYOfColumns[cellAtColumn]=CGRectGetMaxY(cellFrame); 140 141 //显示cell 142 // YYWaterflowViewCell *cell=[self.dadaSource waterflowView:self cellAtIndex:i]; 143 // cell.frame=cellFrame; 144 // [self addSubview:cell]; 145 } 146 147 //设置contentSize 148 CGFloat contentH=maxYOfColumns[0]; 149 for (int i=1; i<numberOfColumns; i++) { 150 if (maxYOfColumns[i]>contentH) { 151 contentH=maxYOfColumns[i]; 152 } 153 } 154 contentH += bottomM; 155 self.contentSize=CGSizeMake(0, contentH); 156 } 157 158 /** 159 * 当UIScrollView滚动的时候也会调用这个方法 160 */ 161 -(void)layoutSubviews 162 { 163 [super layoutSubviews]; 164 165 166 //向数据源索要对应位置的cell 167 NSUInteger numberOfCells=self.cellFrames.count; 168 for (int i=0; i<numberOfCells; i++) { 169 //取出i位置的frame,注意转换 170 CGRect cellFrame=[self.cellFrames[i] CGRectValue]; 171 172 //优先从字典中取出i位置的cell 173 YYWaterflowViewCell *cell=self.displayingCells[@(i)]; 174 175 //判断i位置对应的frame在不在屏幕上(能否看见) 176 if ([self isInScreen:cellFrame]) {//在屏幕上 177 if (cell==nil) { 178 cell= [self.dadaSource waterflowView:self cellAtIndex:i]; 179 cell.frame=cellFrame; 180 [self addSubview:cell]; 181 182 //存放在字典中 183 self.displayingCells[@(i)]=cell; 184 } 185 186 }else //不在屏幕上 187 { 188 if (cell) { 189 //从scrollView和字典中删除 190 [cell removeFromSuperview]; 191 [self.displayingCells removeObjectForKey:@(i)]; 192 193 //存放进缓存池 194 [self.reusableCells addObject:cell]; 195 } 196 } 197 } 198 // NSLog(@"%d",self.subviews.count); 199 } 200 201 -(id)dequeueReusableCellWithIdentifier:(NSString *)identifier 202 { 203 __block YYWaterflowViewCell *reusableCell=nil; 204 [self.reusableCells enumerateObjectsUsingBlock:^(YYWaterflowViewCell *cell, BOOL *stop) { 205 if ([cell.identifier isEqualToString:identifier]) { 206 reusableCell=cell; 207 *stop=YES; 208 } 209 }]; 210 211 if (reusableCell) {//从缓存池中移除(已经用掉了) 212 [self.reusableCells removeObject:reusableCell]; 213 } 214 return reusableCell; 215 } 216 217 #pragma mark cell的事件处理 218 -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 219 { 220 //如果没有点击事件的代理方法,那么就直接返回 221 if (![self.delegate respondsToSelector:@selector(waterflowView:didSelectAtIndex:)]) 222 return; 223 224 //获得手指在屏幕上点击的触摸点 225 UITouch *touch=[touches anyObject]; 226 // CGPoint point=[touch locationInView:touch.view]; 227 CGPoint point=[touch locationInView:self]; 228 229 __block NSNumber *selectIndex=nil; 230 [self.displayingCells enumerateKeysAndObjectsUsingBlock:^(id key, YYWaterflowViewCell *cell, BOOL *stop) { 231 if (CGRectContainsPoint(cell.frame, point)) { 232 selectIndex=key; 233 *stop=YES; 234 } 235 }]; 236 if (selectIndex) { 237 //需要转换 238 [self.delegate waterflowView:self didSelectAtIndex:selectIndex.unsignedIntegerValue]; 239 } 240 241 } 242 #pragma mark-私有方法 243 /** 244 * 判断一个人cell的frame有没有显示在屏幕上 245 */ 246 -(BOOL)isInScreen:(CGRect)frame 247 { 248 // return (CGRectGetMaxY(frame)>self.contentOffset.y)&&(CGRectGetMaxY(frame)<self.contentOffset.y+self.frame.size.height); 249 return (CGRectGetMaxY(frame) > self.contentOffset.y) && 250 (CGRectGetMinY(frame) < self.contentOffset.y + self.frame.size.height); 251 252 } 253 -(CGFloat)marginForType:(YYWaterflowViewMarginType)type 254 { 255 if ([self.delegate respondsToSelector:@selector(waterflowView:marginForType:)]) { 256 return [self.delegate waterflowView:self marginForType:type]; 257 }else 258 { 259 return YYWaterflowViewDefaultMargin; 260 } 261 } 262 263 -(NSUInteger)numberOfColumns 264 { 265 if ([self.dadaSource respondsToSelector:@selector(numberOfColumnsInWaterflowView:)]) { 266 return [self.dadaSource numberOfColumnsInWaterflowView:self]; 267 }else 268 { 269 return YYWaterflowViewDefaultNumberOfClunms; 270 } 271 } 272 273 -(CGFloat)heightAtIndex:(NSUInteger)index 274 { 275 if ([self.delegate respondsToSelector:@selector(waterflowView:heightAtIndex:)]) { 276 return [self.delegate waterflowView:self heightAtIndex:index]; 277 }else 278 { 279 return YYWaterflowViewDefaultCellH; 280 } 281 } 282 @end
实现效果:
![](http://images.cnitblog.com/i/450136/201407/301117481965994.png)
点击对应的cell,能够监听并对点击事件进行处理。
![](http://images.cnitblog.com/i/450136/201407/301118422124224.png)
三、补充说明
示例代码:
![](http://images.cnitblog.com/i/450136/201407/301122243213203.png)
说明:
touch.view指的是子控件(单个cell)以这个cell的左上角为(0,0)进行坐标计算
self指的是整个瀑布流,以整个瀑布流的左上角为(0,0)进行坐标计算
打印查看:
![](http://images.cnitblog.com/i/450136/201407/301124385402131.png)
相关文章推荐
- iOS开发UI篇—自定义瀑布流控件(cell的循环利用)
- iOS开发UI篇—自定义瀑布流控件(蘑菇街数据刷新操作)
- iOS开发UI篇—自定义瀑布流控件(蘑菇街数据刷新操作)
- iOS开发UI篇—自定义瀑布流控件(基本实现)
- iOS开发-UI控件:自定义UITableViewCell 上的多个按钮点击事件处理
- iOS开发UI篇—自定义瀑布流控件(接口设计)
- iOS开发UI篇—自定义瀑布流控件(蘑菇街数据刷新操作)
- iOS开发UI篇—自定义瀑布流控件(接口设计)
- iOS开发UI篇—自定义瀑布流控件(蘑菇街瀑布流)
- iOS开发UI篇—自定义瀑布流控件(蘑菇街瀑布流)
- iOS开发UI篇—自定义瀑布流控件(基本实现)
- iOS开发UI篇—自定义瀑布流控件(基本实现)
- iOS开发UI篇—自定义瀑布流控件(蘑菇街瀑布流)
- 自定义服务器控件开发(2)--事件和事件处理
- iOS开发UI篇—以微博界面为例使用纯代码自定义cell程序编码全过程(一)
- iOS开发UI篇—以微博界面为例使用纯代码自定义cell程序编码全过程(二) - 文顶顶
- iOS开发UI篇—Quartz2D(自定义UIImageView控件)
- iOS开发UI篇—以微博界面为例使用纯代码自定义cell程序编码全过程(二)
- iOS开发UI篇—Quartz2D(自定义UIImageView控件)
- iOS开发UI篇—以微博界面为例使用纯代码自定义cell程序编码全过程