1.建立繼承自UICollectionViewCell的l類ImageCell,將imageView和label聲明成屬性,而後重寫- initWithFrame:方法,初始化內部控件git
- (id)initWithFrame:(CGRect)framegithub
{json
self = [super initWithFrame:frame];數組
if (self) {佈局
[self setupSubviews];atom
}url
return self;spa
}代理
- (void)setupSubviewsorm
{
_imageView = [[UIImageView alloc] initWithFrame:self.bounds];
[self.contentView addSubview:_imageView];
_numberLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 50, 20)];
[_imageView addSubview:_numberLabel];
}
- (void)layoutSubviews
{
[super layoutSubviews];
_imageView.frame = self.bounds;
}
2:建立模型Model類,聲明好屬性
- (void)setValue:(id)value forUndefinedKey:(NSString *)key
{
// if ([key isEqualToString:@"id"]) {
// self.ID = value;
}
- (void)setValue:(id)value forKey:(NSString *)key
{
[super setValue:value forKey:key];
if ([key isEqualToString:@"width"]) {
self.width = [value floatValue];
}
if ([key isEqualToString:@"height"]) {
self.height = [value floatValue];
}
}
3:建立一個瀑布流的佈局類繼承自NSObject,而後設置代理協議,並聲明屬性
4:在這個自定義的WaterFlowLayout中實現各類佈局方法
//存放每一列的高度
@property (nonatomic, retain) NSMutableArray *columnHeightsArray;
//存放 每個item的 屬性 包含 frame以及下標
@property (nonatomic, retain) NSMutableArray *attributesArray;
@end
//獲取最小高度的方法
- (CGFloat)minHeight
{
CGFloat min = 100000;
for (NSNumber *height in _columnHeightsArray) {
CGFloat h = [height floatValue];
if (min > h) {
min = h;
}
}
return min;
}
//獲取最大值
- (CGFloat)maxHeight
{
CGFloat max = 0;
for (NSNumber *height in _columnHeightsArray) {
CGFloat h = [height floatValue];
if (max < h) {
max = h;
}
}
return max;
}
//最小高度的下標
- (NSUInteger)indexOfMinHeight
{
NSUInteger index = 0;
for (int i = 0; i < [_columnHeightsArray count]; i ++) {
CGFloat height = [_columnHeightsArray[i] floatValue];
if (height == [self minHeight]) {
index = i;
return index;
}
}
return index;
}
//重寫父類的佈局方法
- (void)prepareLayout
{
[super prepareLayout];
_attributesArray = [[NSMutableArray alloc] init];
_columnHeightsArray = [[NSMutableArray alloc] initWithCapacity:self.numberOfColumn];
//給列高數組裏面的對象賦初值
for (int i = 0; i < self.numberOfColumn; i ++) {
[_columnHeightsArray addObject:@0.0];
}
CGFloat totalWidth = self.collectionView.frame.size.width;
//建立 每一個item frame中的x、y
CGFloat x = 0;
CGFloat y = 0;
NSUInteger itemCount = [self.collectionView numberOfItemsInSection:0];
for (int i = 0; i < itemCount; i ++) {
//獲得集合視圖中 列間隙的個數
NSUInteger numberOfSpace = self.numberOfColumn - 1;
//代理對象執行代理方法,獲得 item之間的間隙大小
CGFloat spaceWidth = [_delegate collectionView:self.collectionView layout:self minimumInteritemSpacingForSectionAtIndex:0];
//求每列的寬度,也就是每一個item的width
CGFloat width = (totalWidth - spaceWidth * numberOfSpace) / self.numberOfColumn;
//獲取每個itemSize的大小
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
//數據中原始圖片大小
CGSize imageSize = [_delegate collectionView:self.collectionView layout:self sizeForItemAtIndexPath:indexPath];
//經過 約分公式獲得固定寬以後的高度是多少
CGFloat height = width * imageSize.height / imageSize.width;
UICollectionViewLayoutAttributes *attribute = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
//記錄每個item的大小和位置
attribute.frame = CGRectMake(x, y, width, height);
//數組保存每一個item的位置信息
[_attributesArray addObject:attribute];
NSLog(@"item = %d",i);
NSLog(@"x = %.2f y = %.2f width = %.2f height = %.2f",x,y,width,height);
//求列高最小的那一列的下標
NSUInteger minHeightIndex = [self indexOfMinHeight];
//求出最小列的高度
CGFloat minHeight = [_columnHeightsArray[minHeightIndex] floatValue];
//求出行高
CGFloat lineHeight = [_delegate collectionView:self.collectionView layout:self minimumLineSpacingForSectionAtIndex:0];
//上一次總的列高 加上 行高 加上新加上的item的height,纔是如今這一列的總高度
//minHeight爲最小列如今的高度
//lineHeight爲行間距
//height爲新加的item的高
_columnHeightsArray[minHeightIndex] = [NSNumber numberWithFloat:minHeight + lineHeight + height];
//從新算最小列高的下標
minHeightIndex = [self indexOfMinHeight];
//算下一次新加的item的x和y值
x = (spaceWidth + width) * minHeightIndex;
y = [self minHeight];
}
}
//重寫這個方法,能夠返回集合視圖的總高度
- (CGSize)collectionViewContentSize
{
return CGSizeMake(self.collectionView.frame.size.width, [self maxHeight]);
}
//這個方法不寫 集合視圖顯示不出來,這個方法是將保存的每一個item的信息告訴集合視圖,進行顯示。
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
return _attributesArray;
}
//這是重寫的一個佈局方法,和系統的佈局方法就不同了,而後就能夠將這個類當成系統的UICollectionFlowLayout相同的方法使用了
#pragma mark -----WaterFlowDelegate-----
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(WaterFlowLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
Model *model = _dataArray[indexPath.row];
return CGSizeMake(model.width, model.height);
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(WaterFlowLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(0, 0, 0, 0);
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(WaterFlowLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
return 10;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(WaterFlowLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
{
return 5;
}
- (void)viewDidLoad {
[super viewDidLoad];
//從bundle文件中讀取原始數據 json格式
NSString * filePath = [[NSBundle mainBundle] pathForResource:@"Data" ofType:@"json"];
NSData * sourceData = [NSData dataWithContentsOfFile:filePath];
//解析
NSArray * sourceArray = [NSJSONSerialization JSONObjectWithData:sourceData options:NSJSONReadingMutableContainers error:nil];
self.dataArray = [NSMutableArray arrayWithCapacity:40];
//處理數據
for (NSDictionary * dic in sourceArray) {
Model * m = [[Model alloc] init];
[m setValuesForKeysWithDictionary:dic];
[_dataArray addObject:m];
[m release];
}
//建立佈局對象
WaterFlowLayout *flowLayout = [[WaterFlowLayout alloc] init];
flowLayout.delegate = self;
flowLayout.numberOfColumn = 3;
//建立集合視圖
UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:[UIScreen mainScreen].bounds collectionViewLayout:flowLayout];
collectionView.backgroundColor = [UIColor whiteColor];
collectionView.delegate = self;
collectionView.dataSource = self;
//給collectionView註冊一個cell類
[collectionView registerClass:[ImageCell class] forCellWithReuseIdentifier:@"aaa"];
[self.view addSubview:collectionView];
[collectionView release];
[flowLayout release];
// Do any additional setup after loading the view, typically from a nib.
}
#pragma mark -----DataSource-----
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return [_dataArray count];
}
// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
ImageCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"aaa" forIndexPath:indexPath];
//獲取模型
Model *model = self.dataArray[indexPath.row];
NSURL *url = [NSURL URLWithString:model.thumbURL];
[cell.imageView sd_setImageWithURL:url placeholderImage:[UIImage imageNamed:@"屏幕快照 2016-02-25 下午4.17.55.png"]];
// cell.imageView.image = [UIImage imageNamed:@"8.png"];
// cell.numberLabel.text = [NSString stringWithFormat:@"%ld",indexPath.row];
return cell;
}
這裏須要用到一個類SDWebImage的文件,將它上傳到了個人github上。