iOS 瀑布流效果(模仿UITableView重用机制)
来源:互联网 发布:算法分析作业答案 编辑:程序博客网 时间:2024/05/10 20:56
瀑布流:
由很多的格子组成,但是每个格子的宽度和高速都是不确定的,是在动态改变的,就像瀑布一样,是一条线一条线的。说明:使用tableView不能实现瀑布流式的布局,因为tableView是以行为单位的,它要求每行(cell)的高度在内部是一致的。本文章介绍了如何自定义一个瀑布流控件来展示信息,本文介绍模仿UITableView的做法自定义瀑布流包括可重用机制的实现。
接口的实现:
接口的实现包括数据源代理和自身代理所需要用到的方法,我们模仿官方的UITableView可以写出自定义View的代理方法:
#import <UIKit/UIKit.h>typedef enum { JYHWaterfallFlowViewMarginTypeTop, JYHWaterfallFlowViewMarginTypeBottom, JYHWaterfallFlowViewMarginTypeLeft, JYHWaterfallFlowViewMarginTypeRight, JYHWaterfallFlowViewMarginTypeRow, JYHWaterfallFlowViewMarginTypeColumn}JYHWaterfallFlowViewMarginType;@class JYHWaterfallFlowView, JYHWaterfallFlowCell;/** * 数据源代理协议 */@protocol JYHWaterfallFlowDataSource<NSObject>@required/** * 该View共有多少个数据 */- (NSUInteger)numberOfCellsInWaterfallFlowView:(JYHWaterfallFlowView *)waterfallFlowView;/** * 返回对应位置的cell */- (JYHWaterfallFlowCell *)waterfallFlowView:(JYHWaterfallFlowView *)waterfallFlowView cellAtIndex:(NSUInteger)index;@optional/** * 该瀑布流要显示几列 */- (NSUInteger)numberOfColumnsInWaterfallFlowView:(JYHWaterfallFlowView *)waterflowFlowView;@end/** * JYHWaterfallFlowView代理 */@protocol JYHWaterfallFlowDelegate <UIScrollViewDelegate>@optional/** * 第index位置cell对应的高度 */- (CGFloat)waterfallFlowView:(JYHWaterfallFlowView *)waterfallFlowView heightAtIndex:(NSUInteger)index;/** * 选中第index位置的cell */- (void)waterfallFlowView:(JYHWaterfallFlowView *)waterfallFlowView didSelectAtIndex:(NSUInteger)index;/** * 返回间距 */- (CGFloat)waterfallFlowView:(JYHWaterfallFlowView *)waterflowFlowView marginForType:(JYHWaterfallFlowViewMarginType)type;@end@interface JYHWaterfallFlowView : UIScrollView/** * 数据源代理 */@property (nonatomic, weak)id<JYHWaterfallFlowDataSource>dataSource;/** * JYHWaterfallFlowView代理 */@property (nonatomic, weak)id<JYHWaterfallFlowDelegate>waterfallFlowViewdalegate;/** * 刷新数据方法 */- (void)reloadData;/** * 根据标示符从缓存池中查找可重用的Cell * * @param identifier 标示符 * * @return cell */- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier;@end这里需要注意dalegate的命名由于它的父类UIScrollView已经有个叫dalegate的属性了,这里我不小心调了好长时间。。
接下来实现reloadData方法,该方法主要是求出每个cell的Frame里面有一些小算法在里面:
- (void)reloadData { //cell的总数 long numberOfcells = [self.dataSource numberOfCellsInWaterfallFlowView:self]; //View的总列数 long numberOfColumn = [self numberOfColumn]; //间距 CGFloat topM = [self marginForType:JYHWaterfallFlowViewMarginTypeTop]; CGFloat rightM = [self marginForType:JYHWaterfallFlowViewMarginTypeRight]; CGFloat bottomM = [self marginForType:JYHWaterfallFlowViewMarginTypeBottom]; CGFloat leftM = [self marginForType:JYHWaterfallFlowViewMarginTypeLeft]; CGFloat columnM = [self marginForType:JYHWaterfallFlowViewMarginTypeColumn]; CGFloat rowM = [self marginForType:JYHWaterfallFlowViewMarginTypeRow]; //cell的宽度 CGFloat cellW = (self.bounds.size.width - (rightM + leftM) - (numberOfColumn - 1) * columnM) / numberOfColumn; // 用一个C语言数组存放所有列的最大Y值 CGFloat maxYOfColumns[numberOfColumn]; for (int i = 0; i<numberOfColumn; i++) { maxYOfColumns[i] = 0.0; } for (int i = 0; i < numberOfcells; i++) { //cell该放到那一列(最短的那一列),默认为第一列 NSUInteger cellColumn = 0; //最短一列的最大Y值 CGFloat maxOfcellColumn = maxYOfColumns[cellColumn]; //求最短的一列和最短列的最大Y值 for (int j = 1; j < numberOfColumn; j++) { if(maxYOfColumns[j] < maxOfcellColumn) { cellColumn = j; maxOfcellColumn = maxYOfColumns[j]; } } CGFloat cellH = [self hightOfIndex:i]; CGFloat cellX = leftM + cellColumn * (cellW + columnM); CGFloat cellY = 0.0; if (maxOfcellColumn == 0.0) {//首行 cellY = topM; } else { cellY = rowM + maxOfcellColumn; } CGRect cellFrame = CGRectMake(cellX, cellY, cellW, cellH); [self.cellFrames addObject:[NSValue valueWithCGRect:cellFrame]]; //更新最短列的最大Y值 maxYOfColumns[cellColumn] = CGRectGetMaxY(cellFrame); } //设置scrollView的ContentSize CGFloat contentH = maxYOfColumns[0]; for (int j = 1; j<numberOfColumn; j++) { if (maxYOfColumns[j] > contentH) { contentH = maxYOfColumns[j]; } } contentH += bottomM; self.contentSize = CGSizeMake(0, contentH);}
接下来是重点了,重用cell,将不在屏幕上的cell放入到缓存池中,由于scrollView在滚动过程中会调用layoutSubviews这个方法,所以我们可以在这个方法里面进行一些重用操作:
/** * 当ScrollView滚动时会调用这个方法 */- (void)layoutSubviews { [super layoutSubviews]; NSUInteger numberOfCells = [self.cellFrames count]; for (int i = 0; i < numberOfCells; i++) { //取出cellFrame CGRect cellFrame = [self.cellFrames[i] CGRectValue]; //优先取出字典中的cell JYHWaterfallFlowCell *cell = self.displayingCells[@(i)]; if([self isInScreen:cellFrame]) {//在屏幕上出现 if(cell == nil) { cell = [self.dataSource waterfallFlowView:self cellAtIndex:i]; cell.frame = cellFrame; [self addSubview:cell]; //存到字典中 self.displayingCells[@(i)] = cell; } } else { if (cell) { [cell removeFromSuperview]; [self.displayingCells removeObjectForKey:@(i)]; //将cell放入到缓存池中 [self.reusableSet addObject:cell]; } } }}
用访问标识从缓存池中取出cell:
-(id)dequeueReusableCellWithIdentifier:(NSString *)identifier { __block JYHWaterfallFlowCell *resuableCell; [self.reusableSet enumerateObjectsUsingBlock:^(JYHWaterfallFlowCell *cell, BOOL *stop) { if([cell.identifier isEqualToString:identifier]) { resuableCell = cell; *stop = YES; } }]; if(resuableCell) {//用完后将cell从缓存池中移除,防止越积越多 [self.reusableSet removeObject:resuableCell]; } return resuableCell;}
记得在这个waterfallFlowView加入到父控件时像UITableView一样刷新数据:
- (void)willMoveToSuperview:(UIView *)newSuperview { [self reloadData];}
当然还有一些懒加载及一些小方法,在这里就不一一列出了,我把demo上传了,想完全了解的可以下载下来看看,本demo只有第一幅图的代码,第二幅图也就是自定义cell往cell里加东西而已。
Demo连接:http://download.csdn.net/detail/u013672551/9212271
0 0
- iOS 瀑布流效果(模仿UITableView重用机制)
- iOS UItableview重用机制
- 【iOS】UITableView实现的瀑布流效果
- iOS UITableView的重用机制
- IOS开发之----UITableView重用机制
- ios UITableView中Cell的重用机制
- iOS—UITableView Cell重用机制
- IOS开发之----UITableView重用机制
- iOS之UITableView Cell重用机制
- ios UITableView中Cell的重用机制
- IOS之UITableView优化-可重用机制
- IOS-使用UiTableview模仿UICollectionView的效果
- UItableView的重用机制
- UITableView的重用机制
- UITableView的重用机制
- UITableView重用机制
- UITableView重用机制
- UITableView重用机制
- Android代码混淆
- 使用POI读写Excel
- bzoj1652: [Usaco2006 Feb]Treats for the Cows
- 启动listener遇TNS-12555/ TNS-12560 /TNS-00525错误处理
- 集合(泛型及泛型)基本
- iOS 瀑布流效果(模仿UITableView重用机制)
- Dom对象(文档对象模型)
- 高性能服务器架构
- 语言编程感悟
- C语言笔记
- 设计模式六大原则之二:里氏替换原则
- OPTIONS
- 初识WebService
- Java nio