自定义瀑布流
2016-01-14 16:40
218 查看
不规则的图片排列起来,改数据直接用就可以
ZCGFlowLayout.h
ZCGFlowLayout.m
MyCollectionViewCell.h
MyCollectionViewCell.m
Picture.h
Picture.m
ViewController.m
ZCGFlowLayout.h
#import <UIKit/UIKit.h> @class ZCGFlowLayout; @protocol ZCGFlowLayoutDelegate <NSObject> -(CGFloat)ZCGFlowLayout:(ZCGFlowLayout *)flowLayout heightForRowAtIndexPath:(NSIndexPath *)indexPath width:(CGFloat)width; @end @interface ZCGFlowLayout : UICollectionViewLayout //需要设置一下有多少列 //最好不要超过3列 @property(nonatomic,assign)NSInteger columnCounts; //设置距离屏幕四周的边界距离 @property(nonatomic,assign)UIEdgeInsets edgeInsets; //行间距 @property(nonatomic,assign)NSInteger rowSpace; //列间距 @property(nonatomic,assign)NSInteger columnSpace; //定义一个代理人属性 @property(nonatomic,assign)id<ZCGFlowLayoutDelegate>delegate; @end
ZCGFlowLayout.m
#import "ZCGFlowLayout.h" @interface ZCGFlowLayout () //用来记录当前每列的高度 @property(nonatomic,retain)NSMutableDictionary *columnDic; //用来装所有的attributes @property(nonatomic,retain)NSMutableArray *attributesArr; @end @implementation ZCGFlowLayout //自定义瀑布流的核心在于找出每列里最短的,然后需要用一个字典来存储当前列的长度,然后通过遍历找到当前最短的那列 #pragma mark 第一个方法,先重写初始化方法,完成容器初始化 -(instancetype)init{ self=[super init]; if (self) { //先初始化用来存高的字典 self.columnDic=[NSMutableDictionary dictionary]; self.attributesArr=[NSMutableArray array]; } return self; } #pragma mark --瀑布流第二个方法 //重写系统的prepareLayout方法,这个方法当collectionView布局item的时候,该方法会被执行 -(void)prepareLayout{ [super prepareLayout]; //根据设置的边框尺寸,先给每列都设置起始的y,就是边框距离屏幕上方的尺寸 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 (NSInteger i = 0; i < count; i++) { [self setItemFrame:i]; } } #pragma mark 第三个方法,用来设置每一个item的尺寸 -(void)setItemFrame:(NSInteger)index{ //1.首先要获取当前最短的一列 //2.然后设置item的尺寸 //定义一个字符串,用来保存最小的列的下标 __block NSString *minCilumn=@"0"; //这个方法就是用来遍历字典里所有的key和value的 [self.columnDic enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { if([obj floatValue] < [self.columnDic[minCilumn] floatValue]){ minCilumn=key; } }]; //遍历完之后,就可以找到当前最短的那一列 //计算item的宽 //宽 = (375 - 左边界 - 右边界 - 列间距 * (列数-1))/列数 CGFloat width= (375 - self.edgeInsets.left - self.edgeInsets.right - (self.columnCounts - 1) * self.columnSpace) / self.columnCounts; //计算item所摆放的x轴坐标 //x = 左边界 + 当前最短列的下标 * (列间距 + item宽) CGFloat x = self.edgeInsets.left + (self.columnSpace + width) * [minCilumn floatValue]; //指定当前的item是第几分区,第几个 NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:0]; //高度 //通过协议方法,把当前第几个item传回去,调用完就能返回一个已经计算好的高 CGFloat height = [self.delegate ZCGFlowLayout:self heightForRowAtIndexPath:indexPath width:width]; //找到当前最短列的列高 CGFloat y = [self.columnDic[minCilumn]floatValue]; //需要更新一下最下列的列高 = 原有列高 + 高 + 行间距 self.columnDic[minCilumn] = @(y + height +self.rowSpace); //这个类是设置item的frame,透明等属性的,决定了item的属性的信息 UICollectionViewLayoutAttributes *attributes=[UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; //通过attributes设置item的尺寸 attributes.frame=CGRectMake(x, y, width, height); [self.attributesArr addObject:attributes]; } #pragma mark -- 第四个方法:用来告诉layout,布局的时候item的信息 -(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{ return self.attributesArr cbd1 ; } #pragma mark -- 第五个方法:重新设置滚动的范围 -(CGSize)collectionViewContentSize{ //通过字典找到当前列里最长的列 __block NSString *maxKey = @"0"; [self.columnDic enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { if ([obj floatValue] > [self.columnDic[maxKey] floatValue]) { maxKey=key; } }]; //找到最长的列之后,别忘了在最下面,加上底部边界 CGFloat h = [self.columnDic[maxKey] floatValue]+self.edgeInsets.bottom; return CGSizeMake(0, h); } @end
MyCollectionViewCell.h
#import <UIKit/UIKit.h> @interface MyCollectionViewCell : UICollectionViewCell @property(nonatomic,retain)UIImageView *picImageView; @end
MyCollectionViewCell.m
#import "MyCollectionViewCell.h" @implementation MyCollectionViewCell -(instancetype)initWithFrame:(CGRect)frame{ self=[super initWithFrame:frame]; if (self) { [self createView]; } return self; } -(void)createView{ self.picImageView=[[UIImageView alloc] initWithFrame:self.contentView.frame]; [self.contentView addSubview:self.picImageView]; } //防止重用之后还是上一次出现的尺寸,所以为了能显示新的尺寸,需要重新布局 -(void)layoutSubviews{ [super layoutSubviews]; //重新布局cell上的子视图 self.picImageView.frame=self.contentView.frame; } @end
Picture.h
#import <Foundation/Foundation.h> @interface Picture : NSObject @property(nonatomic,copy)NSString *thumbURL; @property(nonatomic,retain)NSNumber *width; @property(nonatomic,retain)NSNumber *height; @end
Picture.m
#import "Picture.h" @implementation Picture -(void)setValue:(id)value forUndefinedKey:(NSString *)key{ } @end
ViewController.m
// // ViewController.m // UI21_自定义瀑布流 // // Created by dllo on 16/1/6. // Copyright © 2016年 dllo. All rights reserved. // #import "ViewController.h" #import "Picture.h" #import "ZCGFlowLayout.h" #import "UIImageView+WebCache.h" #import "MyCollectionViewCell.h" @interface ViewController ()<ZCGFlowLayoutDelegate,UICollectionViewDataSource,UICollectionViewDelegate> @property(nonatomic,retain)NSMutableArray *picArr; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. [self createData]; [self createView]; } -(void)createView{ //创建自定义的layout ZCGFlowLayout *flowLayout=[[ZCGFlowLayout alloc] init]; //设置四周的边框尺寸 flowLayout.edgeInsets = UIEdgeInsetsMake(10, 10, 10, 10); //设置列数 flowLayout.columnCounts= 3; //设置行间距 flowLayout.rowSpace=10; //设置列间距 flowLayout.columnSpace=10; //设置代理人 flowLayout.delegate=self; UICollectionView *collectionView=[[UICollectionView alloc] initWithFrame:self.view.frame collectionViewLayout:flowLayout]; collectionView.delegate=self; collectionView.dataSource=self; [self.view addSubview:collectionView]; //cell注册 [collectionView registerClass:[MyCollectionViewCell class] forCellWithReuseIdentifier:@"reuse"]; } //用来计算item高的协议方法 -(CGFloat)ZCGFlowLayout:(ZCGFlowLayout *)flowLayout heightForRowAtIndexPath:(NSIndexPath *)indexPath width:(CGFloat)width{ //图片的原始尺寸都保存在model里 //计算item的高 = 原始的height * width / 原始的width Picture *pic = self.picArr[indexPath.row]; CGFloat height = [pic.height floatValue] * width / [pic.width floatValue]; return height; } -(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{ return self.picArr.count; } -(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{ MyCollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:@"reuse" forIndexPath:indexPath]; Picture *pic=self.picArr[indexPath.row]; [cell.picImageView sd_setImageWithURL:[NSURL URLWithString:pic.thumbURL]placeholderImage:[UIImage imageNamed:@"c4.jpg"]]; return cell; } -(void)createData{ NSString *filePath=[[NSBundle mainBundle] pathForResource:@"Data(1)" ofType:@"json"]; NSData *data=[NSData dataWithContentsOfFile:filePath]; NSMutableArray *arr=[NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; self.picArr=[NSMutableArray array]; for (NSDictionary *dic in arr) { Picture *pic=[[Picture alloc] init]; [pic setValuesForKeysWithDictionary:dic]; [self.picArr addObject:pic]; } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end
相关文章推荐
- bzoj3514: Codechef MARCH14 GERALD07加强版
- Jquery实现列表项的快速检索
- [IMX6Q][Android5.1]移植笔记 --- uboot_v2015.04移植
- 电气人员操作注意
- Linux 下zip包的压缩与解压
- pod install 失效问题
- bootstrap警示框
- C语言练习代码
- Android 开发 命名规范
- CSS增加web字体
- Unity3D游戏开发技巧Camera实现效果
- Java 网络编程(六) 使用无连接的数据报(UDP)进行通信
- SMS短信的PDU编码规则
- 移动指定文件并可转换格式
- UVa 11077 Find the Permutations(置换+递推)
- MySQL与NoSQL——SQL与NoSQL的融合
- java版字符串编码转换
- Java 网络编程(五) 使用TCP/IP的套接字(Socket)进行通信
- 目录克隆(拷贝)
- Spring-plat-form详细依赖【官网】