标签:blog http 使用 os io strong 文件 数据
一、简单说明


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 -(void)willMoveToSuperview:(UIView *)newSuperview
66 {
67 [self reloadData];
68 }
69
70 #pragma mark-公共方法
71 /**
72 * cell的宽度
73 */
74 -(CGFloat)cellWidth
75 {
76 //cell的列数
77 int numberOfColumns=[self numberOfColumns];
78 CGFloat leftM=[self marginForType:YYWaterflowViewMarginTypeLeft];
79 CGFloat rightM=[self marginForType:YYWaterflowViewMarginTypeRight];
80 CGFloat columnM=[self marginForType:YYWaterflowViewMarginTypeColumn];
81 return (self.frame.size.width-leftM-rightM-(numberOfColumns-1)*columnM)/numberOfColumns;
82 }
83
84 /**
85 * 刷新数据
86 * 1.计算每个cell的frame
87 */
88 -(void)reloadData
89 {
90 /*
91 (1)把字典中的所有的值,都从屏幕上移除
92 (2)清除字典中的所有元素
93 (3)清除cell的frame,每个位置的cell的frame都要重新计算
94 (4)清除可复用的缓存池。
95 */
96
97 [self.displayingCells.allValues makeObjectsPerformSelector:@selector(removeFromSuperview)];
98 [self.displayingCells removeAllObjects];
99 [self.cellFrames removeAllObjects];
100 [self.reusableCells removeAllObjects];
101
102 //cell的总数是多少
103 int numberOfCells=[self.dadaSource numberOfCellsInWaterflowView:self];
104
105 //cell的列数
106 int numberOfColumns=[self numberOfColumns];
107
108 //间距
109 CGFloat leftM=[self marginForType:YYWaterflowViewMarginTypeLeft];
110
111 CGFloat columnM=[self marginForType:YYWaterflowViewMarginTypeColumn];
112 CGFloat topM=[self marginForType:YYWaterflowViewMarginTypeTop];
113 CGFloat rowM=[self marginForType:YYWaterflowViewMarginTypeRow];
114 CGFloat bottomM=[self marginForType:YYWaterflowViewMarginTypeBottom];
115
116 //(1)cell的宽度
117 //cell的宽度=(整个view的宽度-左边的间距-右边的间距-(列数-1)X每列之间的间距)/总列数
118 // CGFloat cellW=(self.frame.size.width-leftM-rightM-(numberOfColumns-1)*columnM)/numberOfColumns;
119 CGFloat cellW=[self cellWidth];
120
121 //用一个C语言的数组来存放所有列的最大的Y值
122 CGFloat maxYOfColumns[numberOfColumns];
123 for (int i=0; i<numberOfColumns; i++) {
124 //初始化数组的数值全部为0
125 maxYOfColumns[i]=0.0;
126 }
127
128
129 //计算每个cell的fram
130 for (int i=0; i<numberOfCells; i++) {
131
132 //(2)cell的高度
133 //询问代理i位置的高度
134 CGFloat cellH=[self heightAtIndex:i];
135
136 //cell处在第几列(最短的一列)
137 NSUInteger cellAtColumn=0;
138
139 //cell所处那列的最大的Y值(当前最短的那一列的最大的Y值)
140 //默认设置最短的一列为第一列(优化性能)
141 CGFloat maxYOfCellAtColumn=maxYOfColumns[cellAtColumn];
142
143 //求出最短的那一列
144 for (int j=0; j<numberOfColumns; j++) {
145 if (maxYOfColumns[j]<maxYOfCellAtColumn) {
146 cellAtColumn=j;
147 maxYOfCellAtColumn=maxYOfColumns[j];
148 }
149 }
150
151 //(3)cell的位置(X,Y)
152 //cell的X=左边的间距+列号*(cell的宽度+每列之间的间距)
153 CGFloat cellX=leftM+cellAtColumn*(cellW +columnM);
154 //cell的Y,先设定为0
155 CGFloat cellY=0;
156 if (maxYOfCellAtColumn==0.0) {//首行
157 cellY=topM;
158 }else
159 {
160 cellY=maxYOfCellAtColumn+rowM;
161 }
162
163 //设置cell的frame并添加到数组中
164 CGRect cellFrame=CGRectMake(cellX, cellY, cellW, cellH);
165 [self.cellFrames addObject:[NSValue valueWithCGRect:cellFrame]];
166
167 //更新最短那一列的最大的Y值
168 maxYOfColumns[cellAtColumn]=CGRectGetMaxY(cellFrame);
169 }
170
171 //设置contentSize
172 CGFloat contentH=maxYOfColumns[0];
173 for (int i=1; i<numberOfColumns; i++) {
174 if (maxYOfColumns[i]>contentH) {
175 contentH=maxYOfColumns[i];
176 }
177 }
178 contentH += bottomM;
179 self.contentSize=CGSizeMake(0, contentH);
180 }
181
182 /**
183 * 当UIScrollView滚动的时候也会调用这个方法
184 */
185 -(void)layoutSubviews
186 {
187 [super layoutSubviews];
188
189
190 //向数据源索要对应位置的cell
191 NSUInteger numberOfCells=self.cellFrames.count;
192 for (int i=0; i<numberOfCells; i++) {
193 //取出i位置的frame,注意转换
194 CGRect cellFrame=[self.cellFrames[i] CGRectValue];
195
196 //优先从字典中取出i位置的cell
197 YYWaterflowViewCell *cell=self.displayingCells[@(i)];
198
199 //判断i位置对应的frame在不在屏幕上(能否看见)
200 if ([self isInScreen:cellFrame]) {//在屏幕上
201 if (cell==nil) {
202 cell= [self.dadaSource waterflowView:self cellAtIndex:i];
203 cell.frame=cellFrame;
204 [self addSubview:cell];
205
206 //存放在字典中
207 self.displayingCells[@(i)]=cell;
208 }
209
210 }else //不在屏幕上
211 {
212 if (cell) {
213 //从scrollView和字典中删除
214 [cell removeFromSuperview];
215 [self.displayingCells removeObjectForKey:@(i)];
216
217 //存放进缓存池
218 [self.reusableCells addObject:cell];
219 }
220 }
221 }
222 // NSLog(@"%d",self.subviews.count);
223 }
224
225 -(id)dequeueReusableCellWithIdentifier:(NSString *)identifier
226 {
227 __block YYWaterflowViewCell *reusableCell=nil;
228 [self.reusableCells enumerateObjectsUsingBlock:^(YYWaterflowViewCell *cell, BOOL *stop) {
229 if ([cell.identifier isEqualToString:identifier]) {
230 reusableCell=cell;
231 *stop=YES;
232 }
233 }];
234
235 if (reusableCell) {//从缓存池中移除(已经用掉了)
236 [self.reusableCells removeObject:reusableCell];
237 }
238 return reusableCell;
239 }
240
241 #pragma mark cell的事件处理
242 -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
243 {
244 //如果没有点击事件的代理方法,那么就直接返回
245 if (![self.delegate respondsToSelector:@selector(waterflowView:didSelectAtIndex:)])
246 return;
247
248 //获得手指在屏幕上点击的触摸点
249 UITouch *touch=[touches anyObject];
250 CGPoint point1=[touch locationInView:touch.view];
251 CGPoint point=[touch locationInView:self];
252 NSLog(@"%@--%@",NSStringFromCGPoint(point),NSStringFromCGPoint(point1));
253
254 __block NSNumber *selectIndex=nil;
255 [self.displayingCells enumerateKeysAndObjectsUsingBlock:^(id key, YYWaterflowViewCell *cell, BOOL *stop) {
256 if (CGRectContainsPoint(cell.frame, point)) {
257 selectIndex=key;
258 *stop=YES;
259 }
260 }];
261 if (selectIndex) {
262 //需要转换
263 [self.delegate waterflowView:self didSelectAtIndex:selectIndex.unsignedIntegerValue];
264 }
265
266 }
267 #pragma mark-私有方法
268 /**
269 * 判断一个人cell的frame有没有显示在屏幕上
270 */
271 -(BOOL)isInScreen:(CGRect)frame
272 {
273 // return (CGRectGetMaxY(frame)>self.contentOffset.y)&&(CGRectGetMaxY(frame)<self.contentOffset.y+self.frame.size.height);
274 return (CGRectGetMaxY(frame) > self.contentOffset.y) &&
275 (CGRectGetMinY(frame) < self.contentOffset.y + self.frame.size.height);
276
277 }
278 -(CGFloat)marginForType:(YYWaterflowViewMarginType)type
279 {
280 if ([self.delegate respondsToSelector:@selector(waterflowView:marginForType:)]) {
281 return [self.delegate waterflowView:self marginForType:type];
282 }else
283 {
284 return YYWaterflowViewDefaultMargin;
285 }
286 }
287
288 -(NSUInteger)numberOfColumns
289 {
290 if ([self.dadaSource respondsToSelector:@selector(numberOfColumnsInWaterflowView:)]) {
291 return [self.dadaSource numberOfColumnsInWaterflowView:self];
292 }else
293 {
294 return YYWaterflowViewDefaultNumberOfClunms;
295 }
296 }
297
298 -(CGFloat)heightAtIndex:(NSUInteger)index
299 {
300 if ([self.delegate respondsToSelector:@selector(waterflowView:heightAtIndex:)]) {
301 return [self.delegate waterflowView:self heightAtIndex:index];
302 }else
303 {
304 return YYWaterflowViewDefaultCellH;
305 }
306 }
307 @end
1 //
2 // YYShopViewController.m
3 // 06-瀑布流
4 //
5 // Created by apple on 14-7-31.
6 // Copyright (c) 2014年 wendingding. All rights reserved.
7 //
8
9 #import "YYShopViewController.h"
10 #import "YYWaterflowView.h"
11 #import "YYWaterflowViewCell.h"
12 #import "YYShop.h"
13 #import "YYShopCell.h"
14 #import "MJExtension.h"
15 #import "MJRefresh.h"
16
17 @interface YYShopViewController ()<YYWaterflowViewDataSource,YYWaterflowViewDelegate>
18 @property(nonatomic,strong)NSMutableArray *shops;
19 @property(nonatomic,strong)YYWaterflowView *waterflowView;
20 @end
21
22 @implementation YYShopViewController
23
24 #pragma mark-懒加载
25 -(NSMutableArray *)shops
26 {
27 if (_shops==nil) {
28 _shops=[NSMutableArray array];
29 }
30 return _shops;
31 }
32 - (void)viewDidLoad
33 {
34 [super viewDidLoad];
35
36 //1.初始化数据
37 NSArray *newShop=[YYShop objectArrayWithFilename:@"2.plist"];
38 [self.shops addObjectsFromArray:newShop];
39
40 //2.创建一个瀑布流
41 YYWaterflowView *waterflow=[[YYWaterflowView alloc]init];
42 waterflow.autoresizingMask=UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
43 waterflow.frame=self.view.bounds;
44 waterflow.delegate=self;
45 waterflow.dadaSource=self;
46 [self.view addSubview:waterflow];
47
48 self.waterflowView=waterflow;
49
50 //3.实现数据的刷新
51 // [waterflow addFooterWithCallback:^{
52 // NSLog(@"上拉数据刷新");
53 // }];
54 //
55 // [waterflow addHeaderWithCallback:^{
56 // NSLog(@"下拉数据刷新");
57 // }];
58
59 [waterflow addHeaderWithTarget:self action:@selector(loadNewShops)];
60 [waterflow addFooterWithTarget:self action:@selector(loadMoreShops)];
61 }
62
63 -(void)loadNewShops
64 {
65 //模拟,只执行一次刷新操作
66 static dispatch_once_t onceToken;
67 dispatch_once(&onceToken, ^{
68 //加载1.plist文件
69 NSArray *newShop=[YYShop objectArrayWithFilename:@"1.plist"];
70 [self.shops insertObjects:newShop atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, newShop.count)]];
71 });
72
73 //模拟网络延迟,2.0秒钟之后执行
74 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
75 //刷新数据
76 [self.waterflowView reloadData];
77
78 //停止刷新
79 [self.waterflowView headerEndRefreshing];
80 });
81 }
82
83 -(void)loadMoreShops
84 {
85 static dispatch_once_t onceToken;
86 dispatch_once(&onceToken, ^{
87 //加载1.plist文件
88 NSArray *newShop=[YYShop objectArrayWithFilename:@"3.plist"];
89 [self.shops addObjectsFromArray:newShop];
90 });
91
92 //模拟网络延迟,2.0秒钟之后执行
93 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
94 //刷新数据
95 [self.waterflowView reloadData];
96
97 //停止刷新
98 [self.waterflowView footerEndRefreshing];
99 });
100
101 }
102
103 #pragma mark-数据源方法
104 -(NSUInteger)numberOfCellsInWaterflowView:(YYWaterflowView *)waterflowView
105 {
106 return self.shops.count;
107 }
108 -(NSUInteger)numberOfColumnsInWaterflowView:(YYWaterflowView *)waterflowView
109 {
110 return 3;
111 }
112 -(YYWaterflowViewCell *)waterflowView:(YYWaterflowView *)waterflowView cellAtIndex:(NSUInteger)index
113 {
114 YYShopCell *cell=[YYShopCell cellWithwaterflowView:waterflowView];
115 cell.shop=self.shops[index];
116 return cell;
117 }
118
119
120 #pragma mark-代理方法
121 -(CGFloat)waterflowView:(YYWaterflowView *)waterflowView heightAtIndex:(NSUInteger)index
122 {
123 YYShop *shop=self.shops[index];
124 //根据Cell的宽度和图片的宽高比 算出cell的高度
125 return waterflowView.cellWidth*shop.h/shop.w;
126 }
127
128 -(void)waterflowView:(YYWaterflowView *)waterflowView didSelectAtIndex:(NSUInteger)index
129 {
130 NSLog(@"点击了第%d个cell",index);
131 }
132
133
134 @end
实现的刷新效果:

标签:blog http 使用 os io strong 文件 数据
原文地址:http://www.cnblogs.com/lcblg/p/3924316.html