自定义瀑布流
2016-04-05 09:13
218 查看
DKFlowLayout类
DKFlowLayout.h
// 在.h里@class, 在.m里#import @class DKFlowLayout; @protocol DKFlowLayoutDelegate <NSObject> - (CGFloat) layout: (DKFlowLayout *)layout heightForItemAtIndexPath:(NSIndexPath *) indexPath width: (CGFloat) width; @end @interface DKFlowLayout : UICollectionViewLayout // 指定有多少列(一般2到4列) @property (nonatomic, assign) NSInteger columnCounts; // 设置距离屏幕四周的边界距离 @property (nonatomic, assign) UIEdgeInsets edgeInsets; // 列间距 @property (nonatomic, assign) NSInteger columnSpace; // 行间距 @property (nonatomic, assign) NSInteger rowSpace; @property (nonatomic, assign) id<DKFlowLayoutDelegate> delegate; @end
DKFlowLayout.m
#define kWidth self.collectionView.frame.size.width @interface DKFlowLayout () // 用来保存每一列的 Y 值 @property (nonatomic, retain) NSMutableDictionary *columnDic; // 用来存放 item 的 attribute 对象 @property (nonatomic, retain) NSMutableArray *attributsArray; @end @implementation DKFlowLayout // 1.初始化方法 - (instancetype) init { if (self = [super init]) { self.columnDic = [NSMutableDictionary dictionary]; self.attributsArray = [NSMutableArray array]; } return self; } // 2.prepareLayout方法: collectionView 布局 item 的时候,该方法会被执行 - (void) prepareLayout { [super prepareLayout]; // 根据列数进行遍历, 给起始的每列都加上上边界的距离 for (NSInteger i = 0; i < self.columnCounts; i++) { NSString *key = [NSString stringWithFormat:@"%ld", i]; self.columnDic[key] = @(self.edgeInsets.top); } // 获取 collectionView 上 item 的个数 NSInteger count = [self.collectionView numberOfItemsInSection:0]; // 循环遍历每个 item for (int i = 0; i < count; i++) { [self setItemFrame:i]; } } // 3.自定义一个方法设置每个 item 的信息 - (void) setItemFrame: (NSInteger) index { // 1.首先获取当前最短的那一列 // 2.设置每个 item 的 frame 的值 // 初始化一个字符串,用它来记录当前最短的列的下标 __block NSString *minColumn = @"0"; // 遍历字典的每个 key 和 value [self.columnDic enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { // 如果遍历得到的值小于默认列的值,就将 key 的值赋值到 minColumn 里 if ([obj floatValue] < [self.columnDic[minColumn] floatValue]) { minColumn = key; } }]; // 宽 = (屏幕宽 - 左边界 - 右边界 - 列间距 * (列数 - 1)) / 列数 CGFloat width = (kWidth - self.edgeInsets.left - self.edgeInsets.right - self.columnSpace * (self.columnCounts - 1)) / self.columnCounts; // x = 左边距 + (宽 + 列间距) * 列的下标(对应当前最短那列的下标) CGFloat x = self.edgeInsets.left + (width + self.columnSpace) * [minColumn floatValue]; // 创建一个 indexPath NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:0]; // 高 CGFloat height = [self.delegate layout:self heightForItemAtIndexPath:indexPath width:width]; // Y // 先找到当前最短那列的 Y 值 CGFloat minY = [self.columnDic[minColumn] floatValue]; // 为最短的列更新 Y 轴的高度 = minY + 高 + 行间距 self.columnDic[minColumn] = @(minY + height + self.rowSpace); // UICollectionViewLayoutAttributes: 设置 item 4000 的 frame, bounds, 透明度等属性 UICollectionViewLayoutAttributes *attribute = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; attribute.frame = CGRectMake(x, minY, width, height); [self.attributsArray addObject:attribute]; } // 4.把所有样式返回,告诉系统如何去布局 - (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect { return self.attributsArray; } // 5.设置滚动的范围 - (CGSize) collectionViewContentSize { // 滚动范围以最长的列作为依据 __block NSString *maxY = @"0"; [self.columnDic enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { if ([obj floatValue] > [self.columnDic[maxY] floatValue]) { maxY = key; } }]; CGFloat h = [self.columnDic[maxY] floatValue] + self.edgeInsets.bottom; return CGSizeMake(0, h); } @end
MyCell类
MyCell.h
@interface MyCell : UICollectionViewCell @property (nonatomic, retain) UIImageView *picImageView; @property (nonatomic, retain) Picture *pic; @end
MyCell.m
@implementation MyCell - (instancetype) initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { self.picImageView = [[UIImageView alloc] init]; [self.contentView addSubview:self.picImageView]; } return self; } - (void) layoutSubviews { [super layoutSubviews]; // 为了避免重用之后造成子视图上的尺寸有问题, 所以在 layoutSubviews 方法重新设置子视图的尺寸 self.picImageView.frame = self.contentView.frame; } // 重写 cell 的 set 方法 - (void) setPic:(Picture *)pic { if (_pic != pic) { [_pic release]; _pic = [pic retain]; } [self.picImageView sd_setImageWithURL:[NSURL URLWithString:_pic.thumbURL]]; } @end
Picture类
.h@interface Picture : NSObject @property (nonatomic, copy) NSString *thumbURL; @property (nonatomic, copy) NSNumber *width; @property (nonatomic, copy) NSNumber *height; @end
eg.
- (void) createData { NSString *path = [[NSBundle mainBundle] pathForResource:@"Data" ofType:@"json"]; NSData *data = [NSData dataWithContentsOfFile:path]; NSArray *tempArr = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; self.arr = [NSMutableArray array]; for (NSDictionary *dic in tempArr) { Picture *pic = [[Picture alloc] init]; [pic setValuesForKeysWithDictionary:dic]; [self.arr addObject:pic]; } } - (void) createView { DKFlowLayout *flowLayout = [[DKFlowLayout alloc] init]; flowLayout.columnCounts = 3; flowLayout.columnSpace = 20; flowLayout.rowSpace = 15; flowLayout.edgeInsets = UIEdgeInsetsMake(10, 10, 10, 10); flowLayout.delegate = self; self.collectionView = [[UICollectionView alloc] initWithFrame:self.view.frame collectionViewLayout:flowLayout]; self.collectionView.dataSource = self; self.collectionView.delegate = self; [self.view addSubview: self.collectionView]; [self.collectionView registerClass:[MyCell class] forCellWithReuseIdentifier:NSStringFromClass([MyCell class])]; self.collectionView.backgroundColor = [UIColor whiteColor]; } - (NSInteger) collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return self.arr.count; } - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { MyCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([MyCell class]) forIndexPath:indexPath]; Picture *pic = self.arr[indexPath.row]; // [cell.picImageView sd_setImageWithURL:[NSURL URLWithString:pic.thumbURL]]; cell.pic = pic; return cell; } - (CGFloat) layout:(DKFlowLayout *)layout heightForItemAtIndexPath:(NSIndexPath *)indexPath width:(CGFloat)width { Picture *pic = self.arr[indexPath.row]; CGFloat height = pic.height.floatValue * width / pic.width.floatValue; return height; } // Data.json [ { "thumbURL": "http://c.hiphotos.baidu.com/baike/w%3D268/sign=1396d7c49922720e7bcee5fc43ca0a3a/b3119313b07eca807f594b41902397dda044ad345982ab0b.jpg", "width": 111.6, "height": 180 }, ... ...
相关文章推荐
- 上海温州商会莅临利尔达物联网科技园参观访问
- js格式化时间
- 用VS2015(vs14)开发PHP7扩展(转+)
- 2016/4/5总结
- redius安装和使用
- 解决maven-resources-plugin prior to 2.4 is not supported
- memset()函数及其作用
- 别老扯什么Hadoop了,你的数据根本不够大!
- oralce 表空间常用操作(查询 删除 增加)
- centos7 开机/etc/rc.local不执行命令的问题
- linux&shell
- Cocoa pods的安装和使用
- Java之I/O流
- QSS样式(1)
- We are a team----sh_6666
- JS+CSS实现闪烁字体效果代码
- Java and C++
- PHP中require()文件包含的正确用法
- 从学生到游戏开发者:我学到的五件事
- Angular JS1学习笔记之一简介与表达式