ViewController.m

1 //
  2 //  ViewController.m
  3 //  IOS_0227_瀑布流
  4 //
  5 //  Created by ma c on 16/2/27.
  6 //  Copyright © 2016年 博文科技. All rights reserved.
  7 //
  8 
  9 #import "ViewController.h"
 10 #import "WaterFlowLayout.h"
 11 #import "MJExtension.h"
 12 #import "MJRefresh.h"
 13 #import "HMShop.h"
 14 #import "ShopCell.h"
 15 
 16 @interface ViewController ()<UICollectionViewDataSource,UICollectionViewDelegate,WaterFlowLayoutDelegate>
 17 
 18 @property (nonatomic, weak) UICollectionView *collectionView;
 19 @property (nonatomic, strong) NSMutableArray *shops;
 20 
 21 @end
 22 
 23 @implementation ViewController
 24 
 25 static NSString *ID = @"shop";
 26 
 27 
 28 - (void)viewDidLoad {
 29     [super viewDidLoad];
 30     
 31     //初始化数据
 32     NSArray *shopArray = [HMShop objectArrayWithFilename:@"1.plist"];
 33     [self.shops addObjectsFromArray:shopArray];
 34     
 35     [self createUI];
 36 }
 37 
 38 - (NSMutableArray *)shops
 39 {
 40     if (!_shops) {
 41         _shops = [NSMutableArray array];
 42     }
 43     return _shops;
 44 }
 45 
 46 - (void)createUI
 47 {
 48 //    CGRect rect = CGRectMake(7, 100, 400, 200);
 49     WaterFlowLayout *layout = [[WaterFlowLayout alloc] init];
 50     UICollectionView *collection = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout];
 51     collection.backgroundColor = [UIColor groupTableViewBackgroundColor];
 52     layout.delegate = self;
 53     collection.dataSource = self;
 54     collection.delegate = self;
 55     [collection registerNib:[UINib nibWithNibName:@"ShopCell" bundle:nil] forCellWithReuseIdentifier:ID];
 56     [self.view addSubview:collection];
 57     self.collectionView = collection;
 58     [self.collectionView addFooterWithTarget:self action:@selector(loadMoreShops)];
 59 }
 60 
 61 - (void)loadMoreShops
 62 {
 63     //初始化数据
 64     NSArray *shopArray = [HMShop objectArrayWithFilename:@"1.plist"];
 65     [self.shops addObjectsFromArray:shopArray];
 66     
 67     [self.collectionView reloadData];
 68     
 69     [self.collectionView footerEndRefreshing];
 70 }
 71 
 72 #pragma mark - WaterFlowLayoutDelegate
 73 
 74 - (CGFloat)waterFlowLayout:(WaterFlowLayout *)waterFlowLayout heightForWidth:(CGFloat)width atIndexPath:(NSIndexPath *)indexPath
 75 {
 76     HMShop *shop = self.shops[indexPath.item];
 77     return shop.height / shop.width * width;
 78 }
 79 
 80 
 81 #pragma mark - UICollectionViewDataSource
 82 
 83 - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
 84 {
 85     return self.shops.count;
 86 }
 87 
 88 - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
 89 {
 90     ShopCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:ID forIndexPath:indexPath];
 91     
 92     cell.shop = self.shops[indexPath.item];
 93     
 94     return cell;
 95 }
 96 
 97 
 98 
 99 
100 @end

WaterFlowLayout.m

1 //
  2 //  WaterFlowLayout.h
  3 //  IOS_0227_瀑布流
  4 //
  5 //  Created by ma c on 16/2/27.
  6 //  Copyright © 2016年 博文科技. All rights reserved.
  7 //
  8 
  9 #import <UIKit/UIKit.h>
 10 @class WaterFlowLayout;
 11 
 12 @protocol WaterFlowLayoutDelegate <NSObject>
 13 
 14 - (CGFloat)waterFlowLayout:(WaterFlowLayout *)waterFlowLayout heightForWidth:(CGFloat)width atIndexPath:(NSIndexPath *)indexPath;
 15 
 16 @end
 17 
 18 @interface WaterFlowLayout : UICollectionViewLayout
 19 
 20 @property (nonatomic, assign) UIEdgeInsets sessionInset;
 21 //列间距
 22 @property (nonatomic, assign) CGFloat columnMargin;
 23 //行间距
 24 @property (nonatomic, assign) CGFloat rowMargin;
 25 //列数
 26 @property (nonatomic, assign) int columnCount;
 27 
 28 @property (nonatomic, strong) id<WaterFlowLayoutDelegate> delegate;
 29 
 30 
 31 @end
 32 
 33 
 34 
 35 
 36 //
 37 //  WaterFlowLayout.m
 38 //  IOS_0227_瀑布流
 39 //
 40 //  Created by ma c on 16/2/27.
 41 //  Copyright © 2016年 博文科技. All rights reserved.
 42 //
 43 
 44 #import "WaterFlowLayout.h"
 45 
 46 @interface WaterFlowLayout ()
 47 //存储每列最大高度Y值
 48 @property (nonatomic, strong) NSMutableDictionary *maxYDict;
 49 @property (nonatomic, strong) NSMutableArray *attrsArray;
 50 
 51 
 52 @end
 53 
 54 @implementation WaterFlowLayout
 55 
 56 - (instancetype)init
 57 {
 58     self = [super init];
 59     if (self) {
 60         self.rowMargin = 10;
 61         self.columnMargin = 10;
 62         self.sessionInset = UIEdgeInsetsMake(10, 10, 10, 10);
 63         self.columnCount = 3;
 64     }
 65     return self;
 66 }
 67 
 68 - (NSMutableDictionary *)maxYDict
 69 {
 70     if (!_maxYDict) {
 71         _maxYDict = [[NSMutableDictionary alloc] init];
 72         for (int i = 0; i < self.columnCount; i++) {
 73             NSString *column = [NSString stringWithFormat:@"%d",i];
 74             _maxYDict[column] = @(self.sessionInset.top);
 75             //NSLog(@"%@",_maxYDict);
 76 
 77         }
 78     }
 79     return _maxYDict;
 80 }
 81 
 82 - (NSMutableArray *)attrsArray
 83 {
 84     if (!_attrsArray) {
 85         _attrsArray = [NSMutableArray array];
 86     }
 87     return _attrsArray;
 88 }
 89 
 90 //布局前准备
 91 - (void)prepareLayout
 92 {
 93     [super prepareLayout];
 94     //NSLog(@"layoutAttributesForElementsInRect");
 95     
 96     //清空最大Y值
 97     for (int i = 0; i < self.columnCount; i++) {
 98         NSString *column = [NSString stringWithFormat:@"%d",i];
 99         _maxYDict[column] = @0;
100     }
101     //计算item属性
102     [self.attrsArray removeAllObjects];
103     NSInteger count = [self.collectionView numberOfItemsInSection:0];
104     
105     for (int i=0; i<count; i++) {
106         NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
107         UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:indexPath];
108         [self.attrsArray addObject:attrs];
109     }
110 }
111 
112 - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
113 {
114     return YES;
115 }
116 
117 //尺寸
118 - (CGSize)collectionViewContentSize
119 {
120     //NSLog(@"collectionViewContentSize");
121     //假设最长的那一列是第0列
122     __block NSString *maxYColumn = @"0";
123     //找出最长的那一列
124     [self.maxYDict enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
125         if ([obj floatValue] > [self.maxYDict[maxYColumn] floatValue]) {
126             maxYColumn = key;
127         }
128     }];
129     return CGSizeMake(0, [self.maxYDict[maxYColumn] floatValue] + self.sessionInset.bottom);
130 }
131 //rect范围内的布局属性
132 - (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
133 {
134 //    //NSLog(@"layoutAttributesForElementsInRect");
135 //    
136 //    for (int i = 0; i < self.columnCount; i++) {
137 //        NSString *column = [NSString stringWithFormat:@"%d",i];
138 //        _maxYDict[column] = @0;
139 //    }
140 //    
141 //    NSMutableArray *array = [NSMutableArray array];
142 //    NSInteger count = [self.collectionView numberOfItemsInSection:0];
143 //    
144 //    for (int i=0; i<count; i++) {
145 //        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
146 //        UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:indexPath];
147 //        [array addObject:attrs];
148 //        
149 //    }
150 //    return array;
151     return self.attrsArray;
152 }
153 //indexPath位置的item的布局属性
154 - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
155 {
156     //NSLog(@"layoutAttributesForItemAtIndexPath");
157     //假设最短的那一列是第0列
158     __block NSString *minYColumn = @"0";
159     //找出最短的那一列
160     [self.maxYDict enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
161         if ([obj floatValue] < [self.maxYDict[minYColumn] floatValue]) {
162             minYColumn = key;
163         }
164     }];
165     //NSLog(@"%@",minYColumn);
166     
167     //计算尺寸
168     CGFloat width = (self.collectionView.frame.size.width - self.sessionInset.left - self.sessionInset.right - (self.columnCount - 1) * self.columnMargin) / self.columnCount;
169     CGFloat height = [self.delegate waterFlowLayout:self heightForWidth:width atIndexPath:indexPath];
170     
171     //计算位置
172     CGFloat x = self.sessionInset.left + (width + self.columnMargin) * [minYColumn intValue];
173     CGFloat y = [self.maxYDict[minYColumn] floatValue] + self.rowMargin;
174     
175     //更新这一列最大Y值
176     self.maxYDict[minYColumn] = @(y + height);
177     
178     //创建属性
179     UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
180     attrs.frame = CGRectMake(x, y, width, height);
181     
182     return attrs;
183 }
184 @end

ShopCell.m

1 //
 2 //  ShopCell.h
 3 //  IOS_0227_瀑布流
 4 //
 5 //  Created by ma c on 16/2/27.
 6 //  Copyright © 2016年 博文科技. All rights reserved.
 7 //
 8 
 9 #import <UIKit/UIKit.h>
10 @class HMShop;
11 @interface ShopCell : UICollectionViewCell
12 
13 @property (nonatomic, strong)  HMShop *shop;
14 
15 @end
16 
17 
18 
19 //
20 //  ShopCell.m
21 //  IOS_0227_瀑布流
22 //
23 //  Created by ma c on 16/2/27.
24 //  Copyright © 2016年 博文科技. All rights reserved.
25 //
26 
27 #import "ShopCell.h"
28 #import "HMShop.h"
29 
30 @interface ShopCell ()
31 
32 @property (weak, nonatomic) IBOutlet UIImageView *imgView;
33 @property (weak, nonatomic) IBOutlet UILabel *lblPrice;
34 
35 @end
36 
37 @implementation ShopCell
38 
39 - (void)awakeFromNib {
40     // Initialization code
41 }
42 
43 - (void)setShop:(HMShop *)shop
44 {
45     _shop = shop;
46     
47     self.imgView.image = [UIImage imageNamed:shop.icon];
48     self.lblPrice.text = shop.price;
49 
50 }
51 
52 @end

HMShop.m

1 //
 2 //  HMShop.h
 3 //  05-黑马瀑布流
 4 //
 5 //  Created by Romeo on 15/11/25.
 6 //  Copyright © 2015年 itheima. All rights reserved.
 7 //
 8 
 9 #import <UIKit/UIKit.h>
10 
11 @interface HMShop : NSObject
12 // 图片
13 @property (nonatomic, copy) NSString *icon;
14 // 价格
15 @property (nonatomic, copy) NSString *price;
16 // 图片的真实高度
17 @property (nonatomic, assign) CGFloat height;
18 // 图片的真实宽度
19 @property (nonatomic, assign) CGFloat width;
20 
21 + (instancetype)shopWithDict:(NSDictionary *)dict;
22 
23 @end
24 
25 
26 
27 //
28 //  HMShop.m
29 //  05-黑马瀑布流
30 //
31 //  Created by Romeo on 15/11/25.
32 //  Copyright © 2015年 itheima. All rights reserved.
33 //
34 
35 #import "HMShop.h"
36 
37 @implementation HMShop
38 
39 + (instancetype)shopWithDict:(NSDictionary *)dict {
40     id obj = [[self alloc] init];
41     [obj setValuesForKeysWithDictionary:dict];
42     return obj;
43 }
44 
45 @end