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