标签:style blog http color os strong io 数据
LWTWaterFlowView.h
1 // 2 // LWTWaterFlowView.h 3 // 瀑布流 4 // 5 // Created by apple on 14-7-29. 6 // Copyright (c) 2014年 lwt. All rights reserved. 7 // 8 9 #import <UIKit/UIKit.h> 10 11 typedef enum { 12 LWTWaterFlowViewMarginTypeTop, // 上 13 LWTWaterFlowViewMarginTypeLeft, // 左 14 LWTWaterFlowViewMarginTypeBotton, // 下 15 LWTWaterFlowViewMarginTypeRight, // 右 16 LWTWaterFlowViewMarginTypeRow, // 行 17 LWTWaterFlowViewMarginTypeColumn, // 列 18 } LWTWaterFlowViewMarginType; 19 20 @class LWTWaterFlowView, LWTWaterFlowViewCell; 21 /** 22 * 瀑布流数据源 23 */ 24 @protocol LWTWaterFlowViewDataSource <NSObject> 25 26 /** 27 * 有多少个数据 28 */ 29 - (NSUInteger)numberOfCellInWaterFlowView:(LWTWaterFlowView *)waterFlowView; 30 31 /** 返回index位置对应的cell */ 32 - (LWTWaterFlowViewCell *)waterFlowView:(LWTWaterFlowView *)waterFlowView cellAtIndex:(NSUInteger)index; 33 @optional 34 /** 一共有多少列 */ 35 - (NSUInteger)numberOfColumnsInWaterFlowView:(LWTWaterFlowView *)waterFlowView; 36 @end 37 38 /** 39 * 瀑布流代理 40 */ 41 @protocol LWTWaterFlowViewDelegate <UIScrollViewDelegate> 42 @optional 43 /** 第index位置cell对应的高度 */ 44 - (CGFloat)waterFlowView:(LWTWaterFlowView *)waterFlowView heightForCellAtIndex:(NSUInteger)index; 45 46 /** 选中第index位置的cell */ 47 - (void)waterFlowView:(LWTWaterFlowView *)waterFlowView didSelectForCellAtIndex:(NSUInteger)index; 48 /** 49 * 间距 50 */ 51 - (CGFloat)waterFlowView:(LWTWaterFlowView *)waterFlowView marginForType:(LWTWaterFlowViewMarginType)type; 52 @end 53 54 @interface LWTWaterFlowView : UIScrollView 55 /** 56 * 数据源 57 */ 58 @property (nonatomic, weak) id<LWTWaterFlowViewDataSource> dataSource; 59 60 /** 61 * 代理 62 */ 63 @property (nonatomic, weak) id<LWTWaterFlowViewDelegate> delegate; 64 65 /** 66 * 刷新数据(只要调用这个方法,会重新向数据源和代理发送请求,请求数据) 67 */ 68 - (void)reloadData; 69 70 /** 71 * cell的宽度 72 */ 73 - (CGFloat)cellWidth; 74 75 /** 76 * 根据标识去缓存池查找可循环利用的cell 77 */ 78 - (id) dequeueReusableCellWithIdentifier:(NSString *)identifier; 79 80 @end
LWTWaterFlowView.m
1 // 2 // LWTWaterFlowView.m 3 // 瀑布流 4 // 5 // Created by apple on 14-7-29. 6 // Copyright (c) 2014年 lwt. All rights reserved. 7 // 8 9 #import "LWTWaterFlowView.h" 10 #import "LWTWaterFlowViewCell.h" 11 12 #define KWaterflowViewDefaultCellH 70 13 #define KWaterflowViewDefaultMargin 8 14 #define KWaterflowViewDefaultNumberOfColumns 3 15 16 @interface LWTWaterFlowView () 17 /** 18 * 所有cell的frame数据 19 */ 20 @property (nonatomic, strong) NSMutableArray *cellFrames; 21 /** 22 * 正在展示的cell 23 */ 24 @property (nonatomic, strong) NSMutableDictionary *displayCells; 25 /** 26 * 缓存池(用Set,存放离开屏幕的cell) 27 */ 28 @property (nonatomic, strong) NSMutableSet *reusableCells; 29 @end 30 31 @implementation LWTWaterFlowView 32 #pragma mark - 初始化 33 - (NSMutableArray *)cellFrames 34 { 35 if (nil == _cellFrames) { 36 _cellFrames = [NSMutableArray array]; 37 } 38 return _cellFrames; 39 } 40 41 - (NSMutableDictionary *)displayCells 42 { 43 if (nil == _displayCells) { 44 _displayCells = [NSMutableDictionary dictionary]; 45 } 46 return _displayCells; 47 } 48 49 - (NSMutableSet *)reusableCells 50 { 51 if (nil == _reusableCells) { 52 _reusableCells = [NSMutableSet set]; 53 } 54 return _reusableCells; 55 } 56 57 - (void)willMoveToSuperview:(UIView *)newSuperview 58 { 59 [self reloadData]; 60 } 61 62 #pragma mark - 公共接口 63 64 - (void)reloadData 65 { 66 // 清空之前的所有数据 67 // 移除正在正在显示cell 68 [self.displayCells.allValues makeObjectsPerformSelector:@selector(removeFromSuperview)]; 69 [self.displayCells removeAllObjects]; 70 [self.cellFrames removeAllObjects]; 71 [self.reusableCells removeAllObjects]; 72 73 // cell的总数 74 int numbersOfCell = [self.dataSource numberOfCellInWaterFlowView:self]; 75 76 // 总列数 77 int numberOfColumns = [self numberOfColumns]; 78 // 间距 79 CGFloat topMargin = [self marginForType:LWTWaterFlowViewMarginTypeTop]; 80 CGFloat leftMargin = [self marginForType:LWTWaterFlowViewMarginTypeLeft]; 81 CGFloat bottomMargin = [self marginForType:LWTWaterFlowViewMarginTypeBotton]; 82 CGFloat rowMargin = [self marginForType:LWTWaterFlowViewMarginTypeRow]; 83 CGFloat columnMargin = [self marginForType:LWTWaterFlowViewMarginTypeColumn]; 84 85 // cell的宽度 86 CGFloat cellWidth = [self cellWidth]; 87 88 // 用一个C语言数组存放所有列的最大Y值 89 CGFloat maxYOfColumns[numberOfColumns]; 90 for (int i = 0; i<numberOfColumns; i++) { 91 maxYOfColumns[i] = 0.0; 92 } 93 94 // 计算所有cell的frame 95 for (int i = 0; i < numbersOfCell ; i++) { 96 // cell的高度 97 CGFloat cellHeight = [self heightAtIndex:i]; 98 99 // cell处在第几列(最短的一列) 100 NSUInteger cellColumn = 0; 101 // cell所处那列的最大的Y值(最短那一列的最大的Y值) 102 NSUInteger maxYOfCellColumn = maxYOfColumns[cellColumn]; 103 // 求出最短的一列 104 for (int j = 1 ; j < numberOfColumns; j++) { 105 if (maxYOfColumns[j] < maxYOfCellColumn) { 106 cellColumn = j; 107 maxYOfCellColumn = maxYOfColumns[j]; 108 } 109 } 110 111 CGFloat cellX = leftMargin + (cellWidth + columnMargin) * cellColumn; 112 113 CGFloat cellY = 0; 114 if (maxYOfCellColumn == 0.0) { // 首行 115 cellY = topMargin; 116 } else { 117 cellY = maxYOfCellColumn + rowMargin; 118 } 119 120 CGRect cellFrame = CGRectMake(cellX, cellY, cellWidth, cellHeight); 121 [self.cellFrames addObject:[NSValue valueWithCGRect:cellFrame]]; 122 123 maxYOfColumns[cellColumn] = CGRectGetMaxY(cellFrame); 124 } 125 126 // 设置contentSize 127 CGFloat contentH = maxYOfColumns[0]; 128 for (int j = 1 ; j < numberOfColumns; j++) { 129 if (maxYOfColumns[j] > contentH) { 130 contentH = maxYOfColumns[j]; 131 } 132 } 133 self.contentSize = CGSizeMake(0, contentH + bottomMargin); 134 135 136 } 137 138 /** 139 * 当UIScrollView滚动的时候也会调用这个方法 140 */ 141 - (void)layoutSubviews 142 { 143 [super layoutSubviews]; 144 145 int numberOfCell = self.cellFrames.count; 146 147 // 向数据源索要对应位置的cell 148 for (int i = 0; i<numberOfCell; i++) { 149 // 取出i位置的frame 150 CGRect cellFrame = [self.cellFrames[i] CGRectValue]; 151 152 // 优先从字典中取出i位置的cell 153 LWTWaterFlowViewCell *cell = self.displayCells[@(i)]; 154 155 // 判断i位置对应的frame在不在屏幕上(能否看见) 156 if ([self isInScreen:cellFrame]) { 157 if (cell == nil) { // 在屏幕上 158 cell = [self.dataSource waterFlowView:self cellAtIndex:i]; 159 cell.frame = cellFrame; 160 [self addSubview:cell]; 161 162 // 存放到字典中 163 [self.displayCells setObject:cell forKey:@(i)]; 164 } 165 } else { // 不在屏幕上 166 if (cell) { 167 // 存放进缓存池 168 [self.reusableCells addObject:cell]; 169 170 // 从scrollView和字典中移除 171 [self.displayCells removeObjectForKey:@(i)]; 172 [cell removeFromSuperview]; 173 } 174 } 175 } 176 } 177 178 /** 179 * cell的宽度 180 */ 181 - (CGFloat)cellWidth 182 { 183 // 总列数 184 int numberOfColumns = [self numberOfColumns]; 185 CGFloat leftMargin = [self marginForType:LWTWaterFlowViewMarginTypeLeft]; 186 CGFloat rightMargin = [self marginForType:LWTWaterFlowViewMarginTypeRight]; 187 CGFloat columnMargin = [self marginForType:LWTWaterFlowViewMarginTypeColumn]; 188 189 return (self.bounds.size.width - leftMargin - rightMargin - (numberOfColumns - 1) * columnMargin) / numberOfColumns; 190 } 191 192 - (id)dequeueReusableCellWithIdentifier:(NSString *)identifier 193 { 194 __block LWTWaterFlowViewCell *reusableCell = nil; 195 [self.reusableCells enumerateObjectsUsingBlock:^(LWTWaterFlowViewCell *cell, BOOL *stop) { 196 if ([cell.identifier isEqualToString:identifier]) { 197 reusableCell = cell; 198 *stop = YES; 199 } 200 }]; 201 202 if (reusableCell) { // 从缓存池中移除 203 [self.reusableCells removeObject:reusableCell]; 204 } 205 206 return reusableCell; 207 } 208 #pragma mark - 私有方法 209 - (BOOL)isInScreen:(CGRect)frame 210 { 211 return (CGRectGetMaxY(frame) > self.contentOffset.y) && (CGRectGetMinY(frame) < (self.contentOffset.y + self.bounds.size.height)); 212 } 213 214 /** 215 * 获取总列数 216 */ 217 - (NSUInteger)numberOfColumns 218 { 219 if ([self.dataSource respondsToSelector:@selector(numberOfColumnsInWaterFlowView:)]) { 220 return [self.dataSource numberOfColumnsInWaterFlowView:self]; 221 } else { 222 return KWaterflowViewDefaultNumberOfColumns; 223 } 224 } 225 226 /** 227 * 获取间距 228 */ 229 - (CGFloat)marginForType:(LWTWaterFlowViewMarginType)type 230 { 231 if ([self.delegate respondsToSelector:@selector(waterFlowView:marginForType:)]) { 232 return [self.delegate waterFlowView:self marginForType:type]; 233 } else { 234 return KWaterflowViewDefaultMargin; 235 } 236 } 237 238 /** 239 * index位置对应cell的高度 240 */ 241 - (CGFloat)heightAtIndex:(NSUInteger)index 242 { 243 if ([self.delegate respondsToSelector:@selector(waterFlowView:heightForCellAtIndex:)]) { 244 return [self.delegate waterFlowView:self heightForCellAtIndex:index]; 245 } else { 246 return KWaterflowViewDefaultCellH; 247 } 248 } 249 250 251 #pragma mark - 事件处理 252 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 253 { 254 if (![self.delegate respondsToSelector:@selector(waterFlowView:didSelectForCellAtIndex:)]) return; 255 256 // 获得触摸点 257 UITouch *touch = [touches anyObject]; 258 CGPoint point = [touch locationInView:self]; 259 260 __block NSNumber *selectedIndex = nil; 261 [self.displayCells enumerateKeysAndObjectsUsingBlock:^(id key, LWTWaterFlowViewCell *cell, BOOL *stop) { 262 if (CGRectContainsPoint(cell.frame, point)) { 263 selectedIndex = key; 264 *stop = YES; 265 } 266 }]; 267 268 if (selectedIndex) { 269 NSUInteger number = selectedIndex.unsignedIntegerValue; 270 [self.delegate waterFlowView:self didSelectForCellAtIndex:number]; 271 } 272 } 273 274 @end
LWTWaterFlowViewCell.h
// // LWTWaterFlowViewCell.h // 瀑布流 // // Created by apple on 14-7-29. // Copyright (c) 2014年 lwt. All rights reserved. // #import <UIKit/UIKit.h> @interface LWTWaterFlowViewCell : UIView @property (nonatomic, copy) NSString *identifier; - (instancetype)initWithIdentifier:(NSString *)identifier; @end
LWTWaterFlowViewCell.m
// // LWTWaterFlowViewCell.m // 瀑布流 // // Created by apple on 14-7-29. // Copyright (c) 2014年 lwt. All rights reserved. // #import "LWTWaterFlowViewCell.h" @implementation LWTWaterFlowViewCell - (id)initWithIdentifier:(NSString *)identifier { self = [super init]; if (self) { self.identifier = identifier; } return self; } @end
标签:style blog http color os strong io 数据
原文地址:http://www.cnblogs.com/wentianblog/p/3878752.html