首页 > 代码库 > 瀑布流
瀑布流
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 @optional34 /** 一共有多少列 */35 - (NSUInteger)numberOfColumnsInWaterFlowView:(LWTWaterFlowView *)waterFlowView;36 @end37 38 /**39 * 瀑布流代理40 */41 @protocol LWTWaterFlowViewDelegate <UIScrollViewDelegate>42 @optional43 /** 第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 @end53 54 @interface LWTWaterFlowView : UIScrollView55 /**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 * 根据标识去缓存池查找可循环利用的cell77 */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 // 设置contentSize127 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)layoutSubviews142 {143 [super layoutSubviews];144 145 int numberOfCell = self.cellFrames.count;146 147 // 向数据源索要对应位置的cell148 for (int i = 0; i<numberOfCell; i++) {149 // 取出i位置的frame150 CGRect cellFrame = [self.cellFrames[i] CGRectValue];151 152 // 优先从字典中取出i位置的cell153 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)cellWidth182 {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 *)identifier193 {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)frame210 {211 return (CGRectGetMaxY(frame) > self.contentOffset.y) && (CGRectGetMinY(frame) < (self.contentOffset.y + self.bounds.size.height));212 }213 214 /**215 * 获取总列数216 */217 - (NSUInteger)numberOfColumns218 {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)type230 {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)index242 {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 *)event253 {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
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。