【代碼筆記】自訂布局實現瀑布流,布局瀑布
檔案目錄如下
動畫如下:
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