iOS-不规则瀑布流-瀑布流图片-
iOS-不规则瀑布流-瀑布流图片-

iOS-不规则瀑布流-瀑布流图片-
iOS-不规则瀑布流-瀑布流图片-
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



iOS-不规则瀑布流-瀑布流图片-
//
// 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


iOS-不规则瀑布流-瀑布流图片-
iOS-不规则瀑布流-瀑布流图片-
iOS-不规则瀑布流-瀑布流图片-
iOS-不规则瀑布流-瀑布流图片-
iOS-不规则瀑布流-瀑布流图片-
iOS-不规则瀑布流-瀑布流图片-

//
// 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



屏幕快照 2016-03-10 下午4.08.17.png
//
// 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


屏幕快照 2016-03-10 下午4.08.24.png
//
// 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



屏幕快照 2016-03-10 下午4.09.16.png
//
// 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


屏幕快照 2016-03-10 下午4.10.04.png
屏幕快照 2016-03-10 下午4.10.14.png
屏幕快照 2016-03-10 下午4.10.24.png
//
// 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