首页 > 代码库 > 瀑布流

瀑布流

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
View Code

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
View Code

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
View Code

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
View Code