iOS-不规则瀑布流-瀑布流图片-
//
// ViewController.m
// UI21_不规则瀑布流
//
// Created by YIem on 16/3/9.
// Copyright © 2016年 YIem. All rights reserved.
//
import "ViewController.h"
import "CollectionViewCell.h"
import "Model.h"
import "YTCollectionViewLayout.h"
@interface ViewController ()<UICollectionViewDataSource, UICollectionViewDelegate, YTCollectionViewLayoutDelegate>
@property (nonatomic, retain) NSMutableArray *dataArr;
@end
@implementation ViewController
(void)viewDidLoad {
[super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. self.view.backgroundColor = [UIColor whiteColor];
// UICollectionViewFlowLayout *flowL = [[[UICollectionViewFlowLayout alloc] init] autorelease];
// flowL.minimumInteritemSpacing = 10;
// flowL.minimumLineSpacing = 10;
// flowL.itemSize = CGSizeMake(120, 150);
// flowL.footerReferenceSize = CGSizeMake(10, 10);
// flowL.headerReferenceSize = CGSizeMake(10, 10);
// flowL.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10);
// // 宽度= (屏幕宽度 - 左间距 - 右间距 - 列间距* (列数 -1)) / 列数
// CGFloat width = ([UIScreen mainScreen].bounds.size.width - 10 - 10 -10 *(3 - 1)) / 3;
// flowL.itemSize = CGSizeMake(120, 100);
pragma - YTCollectionViewLayout
// YTCollectionViewLayout
YTCollectionViewLayout *flowL = [[YTCollectionViewLayout alloc] init];
flowL.interitemCount = 3;
flowL.interitemSpacing = 10;
flowL.lineSpacing = 10;
flowL.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10);
// 协议
flowL.delegate = self;
// flowL.scrollDirection = UICollectionViewScrollDirectionVertical;
UICollectionView *collectV = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:flowL];
collectV.backgroundColor = [UIColor yellowColor];
collectV.dataSource = self;
collectV.delegate = self;
[self.view addSubview:collectV];
[collectV release];
[self Data];
[collectV registerClass:[CollectionViewCell class] forCellWithReuseIdentifier:@"cell"];
}
(void)Data
{NSString *filePath = [[NSBundle mainBundle]pathForResource:@"Data" ofType:@"json"];
NSData *data = [NSData dataWithContentsOfFile:filePath];
NSArray *arr = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
self.dataArr = [NSMutableArray array];
for (NSDictionary *dic in arr) {Model *model = [[Model alloc] init]; [model setValuesForKeysWithDictionary:dic]; [self.dataArr addObject:model]; [model release];
}
}
pragma - (协议) 向YTCollectionViewLayout传人 计算好的 高度
- (CGFloat)heightWithIndex:(NSIndexPath *)indexPath width:(CGFloat)width
{
Model *model = [self.dataArr objectAtIndex:indexPath.row];
// 高度 = 原高度 / 原宽度 * 设置宽度CGFloat height = [model.height doubleValue] / [model.width doubleValue] *width;
return height;
} - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return self.dataArr.count;
} - (UICollectionViewCell )collectionView:(UICollectionView )collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
cell.backgroundColor = [UIColor grayColor];
cell.model = [self.dataArr objectAtIndex:indexPath.row];return cell;
}
(void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.
}
@end
//
// YTCollectionViewLayout.h
// UI21_不规则瀑布流
//
// Created by YIem on 16/3/9.
// Copyright © 2016年 YIem. All rights reserved.
//
import <UIKit/UIKit.h>
@protocol YTCollectionViewLayoutDelegate <NSObject>
- (CGFloat)heightWithIndex:(NSIndexPath *)indexPath width:(CGFloat)width;
@end
@interface YTCollectionViewLayout : UICollectionViewLayout
// 协议 把高度传过来
@property (nonatomic, assign) id<YTCollectionViewLayoutDelegate> delegate;
@property (nonatomic, assign) CGFloat lineSpacing;
@property (nonatomic, assign) CGFloat interitemSpacing;
@property (nonatomic, assign) NSInteger interitemCount;
@property (nonatomic, assign) UIEdgeInsets sectionInset;
@end
//
// YTCollectionViewLayout.m
// UI21_不规则瀑布流
//
// Created by YIem on 16/3/9.
// Copyright © 2016年 YIem. All rights reserved.
//
import "YTCollectionViewLayout.h"
@interface YTCollectionViewLayout ()
@property (nonatomic, retain) NSMutableArray *itemArr;
@property (nonatomic, retain) NSMutableDictionary *heightDic;
@end
@implementation YTCollectionViewLayout
(void)dealloc
{[_itemArr release]; [_heightDic release]; [super dealloc];
}
warning 2 - (系统方法) - 初始化开变量空间
(instancetype)init
{
self = [super init];
if (self) {self.itemArr = [NSMutableArray array]; self.heightDic = [NSMutableDictionary dictionary];
}
return self;
}
warning 3 - (系统方法) - item布局前准备方法, 只在布局前调用一次
(void)prepareLayout
{
[super prepareLayout];for (NSInteger i = 0; i < self.interitemCount; i++) {
// 转 NSNumber *val = [NSNumber numberWithDouble:self.sectionInset.top]; NSString *key = [NSString stringWithFormat:@"%ld", i]; [self.heightDic setObject:val forKey:key];
}
// 系统的collectionView属性, 指向布局对象添加到的collectionView
// numberOfItemInSection系统方法, 某一分区下的item数
for (NSInteger i = 0; i < [self.collectionView numberOfItemsInSection:0]; i++) {// 开始的和谁比
__block NSString *minHeightKey = @"0";
[self.heightDic enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { // 获取最短的val对应的Key if ([obj doubleValue] < [[self.heightDic objectForKey:minHeightKey] doubleValue]) { minHeightKey = key; } }];
pragma - 计算坐标 及 大小
// 宽度 = (屏幕宽度 - 左间距 - 右间距 - 列间距* (列数 -1)) / 列数
CGFloat width = ([UIScreen mainScreen].bounds.size.width - self.sectionInset.left - self.sectionInset.right - self.interitemSpacing * (self.interitemCount - 1)) / self.interitemCount;
// X = 左间距 +(item宽度 + 列间距) * 最短item所在列号
CGFloat x = self.sectionInset.left + (width + self.interitemSpacing) * [minHeightKey integerValue];
// Y = 字典中对应的最小高度(注意; 更新最小高度时对应将行间距加入)
CGFloat y =[[self.heightDic objectForKey:minHeightKey] doubleValue];
// 高度
// 创建
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
// 高度 (计算好传过来的)
CGFloat height = [self.delegate heightWithIndex:indexPath width:width];
// 更新高度
//
NSNumber *heightVal = [NSNumber numberWithDouble:(height + self.lineSpacing) + y];
[self.heightDic setObject:heightVal forKey:minHeightKey];
//
UICollectionViewLayoutAttributes *attribute = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
attribute.frame = CGRectMake(x , y, width, height);
[self.itemArr addObject:attribute];
}
}
warning 1 -(系统方法) - 返回给系统所有的item大小及坐标
- (NSArray<UICollectionViewLayoutAttributes > )layoutAttributesForElementsInRect:(CGRect)rect
{
return self.itemArr;
}
warning 4 - (系统方法) - 设置滚动范围
(CGSize)collectionViewContentSize
{
// 获取最高列的高度
__block NSString *maxHeightKey = @"0";
[self.heightDic enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {if ([obj doubleValue] > [[self.heightDic objectForKey:maxHeightKey] doubleValue]) { maxHeightKey = key; }
}];
CGFloat height = [[self.heightDic objectForKey:maxHeightKey] doubleValue];
return CGSizeMake(0, height);
}
@end
//
// Model.h
// UI21_不规则瀑布流
//
// Created by YIem on 16/3/9.
// Copyright © 2016年 YIem. All rights reserved.
//
import <Foundation/Foundation.h>
@interface Model : NSObject
@property (nonatomic, copy) NSString *thumbURL;
@property (nonatomic, copy) NSString *width;
@property (nonatomic, copy) NSString *height;
@end
//
// Model.m
// UI21_不规则瀑布流
//
// Created by YIem on 16/3/9.
// Copyright © 2016年 YIem. All rights reserved.
//
import "Model.h"
@implementation Model
(void)dealloc
{[_height release]; [_width release]; [_thumbURL release]; [super dealloc];
}
(void)setValue:(id)value forUndefinedKey:(NSString *)key
{}
@end
//
// CollectionViewCell.h
// UI21_不规则瀑布流
//
// Created by YIem on 16/3/9.
// Copyright © 2016年 YIem. All rights reserved.
//
import <UIKit/UIKit.h>
@class Model;
@interface CollectionViewCell : UICollectionViewCell
@property (nonatomic, retain) Model *model;
@end
//
// CollectionViewCell.m
// UI21_不规则瀑布流
//
// Created by YIem on 16/3/9.
// Copyright © 2016年 YIem. All rights reserved.
//
import "CollectionViewCell.h"
import "UIImageView+WebCache.h"
import "Model.h"
@interface CollectionViewCell ()
@property (nonatomic, retain) UIImageView *imageV;
@end
@implementation CollectionViewCell
(instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {[self createImage];
}
return self;
}- (void)createImage
{
self.backgroundColor = [UIColor blackColor];
// 大小 不要放这里 - 不然会重用
self.imageV = [[UIImageView alloc] init];[self.contentView addSubview:_imageV];
[_imageV release];
} (void)setModel:(Model *)model
{
if (_model != model) {[_model release]; _model = [model retain];
}
[self.imageV sd_setImageWithURL:[NSURL URLWithString:self.model.thumbURL] placeholderImage:[UIImage imageNamed:@"1.png"]];
// [_imageV sd_setImageWithURLStr:self.model.thumbURL];
}
// 当Frame发生改变时会触发
// 当frame相同时不会触发
// 在appapplyLayoutAttributes之后调用, 最后调用
(void)layoutSubviews
{[super layoutSubviews]; self.imageV.frame = self.contentView.bounds;
}
// 布局时会触发 (必然触发)
//- (void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes
//{
// [super applyLayoutAttributes:layoutAttributes];
// // 防止imageV 大小与重用池取出的cell不匹配
// self.imageV.frame = self.contentView.bounds;
//}
@end