【代码笔记】自定义布局实现瀑布流

利用collectionView实现瀑布流的效果,

文件目录如下

动画效果图如下:

 1 //ViewController文件
 2 
 3 #import "ViewController.h"
 4 #import "LYWaterFlowLayout.h"
 5 #import "LYWaterCell.h"
 6 #import "LYShopModel.h"
 7 
 8 @interface ViewController ()<UICollectionViewDataSource>
 9 @property(nonatomic,strong)NSArray *shops;
10 
11 
12 @end
13 
14 @implementation ViewController
15  static NSString *ID = @"water";
16 
17 - (NSArray *)shops{
18     
19     if (_shops == nil) {
20 //        1.读取文件
21         NSString *path =  [[NSBundle mainBundle ]pathForResource:@"1.plist" ofType:nil];
22        NSArray *dictArray =  [NSArray arrayWithContentsOfFile:path];
23 //        2.字典转模型
24         NSMutableArray *tempArray = [NSMutableArray array];
25         for (NSDictionary *dict in dictArray) {
26             LYShopModel *shop = [LYShopModel shopWithDict:dict];
27             [tempArray addObject:shop];
28             
29         }
30         _shops = tempArray;
31         
32         
33         
34     }
35     return _shops;
36 }
37 
38 - (void)viewDidLoad {
39     [super viewDidLoad];
40     // Do any additional setup after loading the view, typically from a nib.
41 //    0.自定义布局
42     LYWaterFlowLayout *waterFlowLayout = [[LYWaterFlowLayout alloc]init];
43 //    0.1.传递外界数组到内部
44     waterFlowLayout.shops = self.shops;
45     
46 //    1.创建collectionView
47     UICollectionView *collectionView = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) collectionViewLayout:waterFlowLayout];
48 //    2.设置数据源
49     collectionView.dataSource = self;
50 ////    3.设置代理
51 //    collectionView.delegate = self;
52     
53 
54 //    3.添加
55     [self.view addSubview:collectionView];
56 //    4.注册cell
57     [collectionView registerNib:[UINib nibWithNibName:@"LYWaterCell" bundle:nil] forCellWithReuseIdentifier:ID];
58     
59     
60 }
61 
62 - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
63     
64     return  1;
65     
66 }
67 
68 - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
69     
70     return self.shops.count;
71 }
72 
73 - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
74     
75     
76 //    1.创建cell
77    
78     LYWaterCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:ID forIndexPath:indexPath];
79 //    2.赋值
80 //
81 //    cell.backgroundColor = [UIColor redColor];
82 //    2.1获取模型
83     LYShopModel *shop = self.shops[indexPath.item];
84     cell.shop = shop;
85     
86     cell.indexPath=indexPath;
87 //   3.返回cell
88     return cell;
89     
90     
91 }
92 
93 @end
 1 //LYWaterCell文件
 2 #import <UIKit/UIKit.h>
 3 @class LYShopModel;
 4 
 5 @interface LYWaterCell : UICollectionViewCell
 6 @property(nonatomic,strong)LYShopModel *shop;
 7 
 8 @property(nonatomic,strong)NSIndexPath *indexPath;
 9 
10 @end
11 
12 
13 
14 
15 
16 #import "LYWaterCell.h"
17 #import "LYShopModel.h"
18 
19 @interface LYWaterCell()
20 
21 @property (weak, nonatomic) IBOutlet UIImageView *iconView;
22 @property (weak, nonatomic) IBOutlet UILabel *priceLabel;
23 
24 @end
25 @implementation LYWaterCell
26 - (void)setShop:(LYShopModel *)shop{
27     
28     _shop = shop;
29   
30     self.iconView.image = [UIImage imageNamed:shop.icon];
31     //self.priceLabel.text = shop.price;
32     
33 }
34 -(void)setIndexPath:(NSIndexPath *)indexPath{
35     
36     _indexPath = indexPath;
37     self.priceLabel.text = self.shop.price;
38     
39 }
40 
41 @end
  1 //LYWaterFlowLayout文件
  2 #import <UIKit/UIKit.h>
  3 
  4 @interface LYWaterFlowLayout : UICollectionViewFlowLayout
  5 
  6 
  7 
  8 @property(nonatomic,strong)NSArray *shops;
  9 
 10 
 11 @end
 12 
 13 
 14 
 15 
 16 
 17 int const column = 3;
 18 #import "LYWaterFlowLayout.h"
 19 #import "LYShopModel.h"
 20 
 21 @interface LYWaterFlowLayout()
 22 
 23 @property(nonatomic,strong)NSMutableArray *maxYs;
 24 @end
 25 
 26 @implementation LYWaterFlowLayout
 27 - (NSMutableArray *)maxYs{
 28     
 29     if (_maxYs == nil) {
 30         _maxYs = [NSMutableArray array];
 31         NSLog(@"%@",_maxYs);
 32         
 33     }
 34     
 35     return _maxYs;
 36 }
 37 
 38 /**
 39  *  用来设置每一个对应位置的item属性
 40  *
 41  *  @param indexPath 用来确定每一item具体位置
 42  *
 43  *  @return 用来设置每一个item的属性
 44  */
 45 -(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{
 46     //NSLog(@"调用了layoutAttributesForItemAtIndexPath");
 47     //    1.确定上左下右间距
 48   
 49     UIEdgeInsets edge = UIEdgeInsetsMake(10, 10, 10, 10);
 50    //     2.确定宽度
 51 //        2.1确定列数
 52   
 53 //        2.2确定行间距和列间距
 54     CGFloat rowMargin = 10;
 55     CGFloat colMargin = 10;
 56     
 57     CGFloat itemW = (self.collectionView.frame.size.width - edge.left - edge.right - (column - 1)*colMargin)/column;    
 58 //        3.确定高度
 59 //        3.1获取对应item的模型
 60     LYShopModel *shop = self.shops[indexPath.item];
 61 //    itemW/itemh = shop.width/shop.height;
 62 
 63     CGFloat itemH = shop.height *itemW/shop.width;
 64     
 65 //    CGFloat itmeH = 100+ arc4random_uniform(100);
 66 //        4.确定位置
 67     
 68 //        4.1获取最小的最大y值
 69 //        4.2用一个值来记录最小的最大y值
 70     CGFloat minMaxY = MAXFLOAT;
 71 //        4.3记录最小的最大的y值所在的列号;
 72     NSInteger minMaxCol = 0;
 73     for (int i = 0; i <column; i ++) {
 74         CGFloat maxY = [self.maxYs[i]doubleValue];
 75         if (maxY < minMaxY) {
 76             minMaxY = maxY;
 77             minMaxCol = i;
 78         }
 79     }
 80 //     4.4设置item的x值
 81     CGFloat itemX = edge.left + (itemW + colMargin) *minMaxCol;
 82     CGFloat itemY = minMaxY + rowMargin;
 83 //    5.获取每一个对应位置的item的属性
 84     UICollectionViewLayoutAttributes *attr = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
 85 //    6.设置属性的frame
 86     attr.frame = CGRectMake(itemX, itemY, itemW, itemH);
 87 //    7.累加最小的最大的y值
 88 //    minMaxY = CGRectGetMaxY(attr.frame);
 89     self.maxYs[minMaxCol]= @(CGRectGetMaxY(attr.frame));
 90     
 91     
 92     
 93 //    8.返回属性
 94     return  attr;
 95 
 96 }
 97 /**
 98  *  用来设置给定范围内所有的属性
 99  *
100  *  @param rect <#rect description#>
101  *
102  *  @return <#return value description#>
103  */
104 - (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{
105    // NSLog(@"调用了layoutAttributesForElementsInRect");
106 //    0.清空原来的所有的值
107    // [self.maxYs removeAllObjects];
108 //    1.设置数组的值
109     for (int i = 0 ; i <column;i ++) {
110        // [self.maxYs addObject:@(0)];
111         self.maxYs[i]=@(0);
112     }
113     
114     
115 //    2.创建可变数组
116     NSMutableArray *attrs = [NSMutableArray array];
117     
118 //
119 //    3.获取所有的item的属性的个数
120     NSInteger count = [self.collectionView numberOfItemsInSection:0];
121 //    4.遍历多次,添加对应的属性值
122     for (int i = 0; i < count; i ++ ) {
123         NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
124         
125         UICollectionViewLayoutAttributes *attr = [self layoutAttributesForItemAtIndexPath:indexPath];
126     
127         [attrs addObject:attr];
128      //   NSLog(@"%@",attr);
129         
130     }
131     return attrs;
132 
133     
134 }
135 - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{
136   //  NSLog(@"调用了shouldInvalidateLayoutForBoundsChange");
137     return YES;
138 }
139 /**
140  *  用来设置collectionView的滚动范围
141  *
142  *  @return <#return value description#>
143  */
144 
145 - (CGSize)collectionViewContentSize{
146     // NSLog(@"调用了collectionViewContentSize");
147 //    1.获取最大最大y值
148     CGFloat maxMaxY = 0;
149 //    1.1.记录最大的最大y值
150     if (self.maxYs.count) {
151          maxMaxY = [self.maxYs[0]doubleValue];
152         for (int i = 1; i < column; i ++) {
153             //        1.2获取每一个值
154             CGFloat maxY = [self.maxYs[i]doubleValue];
155             if (maxY > maxMaxY) {
156                 maxMaxY = maxY;
157             }
158             
159         }
160 
161     }
162     
163    
164     return CGSizeMake(0, maxMaxY);
165     
166 
167 }
168 
169 @end
 1 //LYShopModel文件
 2 #import <Foundation/Foundation.h>
 3 
 4 @interface LYShopModel : NSObject
 5 @property(nonatomic,copy)NSString *icon;
 6 @property(nonatomic,copy)NSString *price;
 7 @property(nonatomic,assign)int height;
 8 @property(nonatomic,assign)int width;
 9 - (instancetype)initWithDict:(NSDictionary *)dict;
10 + (instancetype)shopWithDict:(NSDictionary *)dict;
11 
12 @end
13 
14 
15 
16 
17 
18 #import "LYShopModel.h"
19 
20 @implementation LYShopModel
21 
22 - (instancetype)initWithDict:(NSDictionary *)dict{
23     
24     if (self = [super init]) {
25         [self setValuesForKeysWithDictionary:dict];
26     }
27     return self;
28 }
29 + (instancetype)shopWithDict:(NSDictionary *)dict{
30     
31     return [[self alloc]initWithDict:dict];
32 }
33 
34 @end
原文地址:https://www.cnblogs.com/liyy2015/p/5237083.html