你的位置:首页 > 操作系统

[操作系统]【代码笔记】自定义布局实现瀑布流


文件目录如下

 

 

动画效果图如下:

 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 @end13 14 @implementation ViewController15 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.创建collectionView47   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.注册cell57   [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.创建cell77  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.返回cell88   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 @end11 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 @end25 @implementation LYWaterCell26 - (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 @end13 14 15 16 17 18 #import "LYShopModel.h"19 20 @implementation LYShopModel21 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