自定义UICollectionViewLayout—实现瀑布流效果
来源:互联网 发布:centos与ubuntu 编辑:程序博客网 时间:2024/05/21 09:55
最终效果:
用到的第三方框架:
1.自定义UICollectionViewLayout实现瀑布流布局效果
//// WaterflowLayout.h// 0104-瀑布流#import <UIKit/UIKit.h>@class WaterflowLayout;@protocol WaterflowLayoutDelegate <NSObject>- (CGFloat)waterflowLayout:(WaterflowLayout *)waterflowLayout heightForWidth:(CGFloat)width atIndexPath:(NSIndexPath *)indexPath;@end@interface WaterflowLayout : UICollectionViewLayout@property (nonatomic, assign) UIEdgeInsets sectionInset;/** 每一列之间的间距 */@property (nonatomic, assign) CGFloat columnMargin;/** 每一行之间的间距 */@property (nonatomic, assign) CGFloat rowMargin;/** 显示多少列 */@property (nonatomic, assign) int columnsCount;@property (nonatomic, weak) id<WaterflowLayoutDelegate> delegate;@end
//// WaterflowLayout.m// 0104-瀑布流#import "WaterflowLayout.h"@interface WaterflowLayout()/** 这个字典用来存储每一列最大的Y值(每一列的高度) */@property (nonatomic, strong) NSMutableDictionary *maxYDict;/** 存放所有的布局属性 */@property (nonatomic, strong) NSMutableArray *attrsArray;@end@implementation WaterflowLayout- (NSMutableDictionary *)maxYDict{ if (!_maxYDict) { self.maxYDict = [[NSMutableDictionary alloc] init]; } return _maxYDict;}- (NSMutableArray *)attrsArray{ if (!_attrsArray) { self.attrsArray = [[NSMutableArray alloc] init]; } return _attrsArray;}- (instancetype)init{ if (self = [super init]) { self.columnMargin = 10; self.rowMargin = 10; self.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10); self.columnsCount = 3; } return self;}- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{ return YES;}/** * 每次布局之前的准备 */- (void)prepareLayout{ [super prepareLayout]; // 1.清空最大的Y值 for (int i = 0; i<self.columnsCount; i++) { NSString *column = [NSString stringWithFormat:@"%d", i]; self.maxYDict[column] = @(self.sectionInset.top); } // 2.计算所有cell的属性 [self.attrsArray removeAllObjects]; NSInteger count = [self.collectionView numberOfItemsInSection:0]; for (int i = 0; i<count; i++) { UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]]; [self.attrsArray addObject:attrs]; }}/** * 返回所有的尺寸 */- (CGSize)collectionViewContentSize{ __block NSString *maxColumn = @"0"; [self.maxYDict enumerateKeysAndObjectsUsingBlock:^(NSString *column, NSNumber *maxY, BOOL *stop) { if ([maxY floatValue] > [self.maxYDict[maxColumn] floatValue]) { maxColumn = column; } }]; return CGSizeMake(0, [self.maxYDict[maxColumn] floatValue] + self.sectionInset.bottom);}/** * 返回indexPath这个位置Item的布局属性 */- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{ // 假设最短的那一列的第0列 __block NSString *minColumn = @"0"; // 找出最短的那一列 [self.maxYDict enumerateKeysAndObjectsUsingBlock:^(NSString *column, NSNumber *maxY, BOOL *stop) { if ([maxY floatValue] < [self.maxYDict[minColumn] floatValue]) { minColumn = column; } }]; // 计算尺寸 CGFloat width = (self.collectionView.frame.size.width - self.sectionInset.left - self.sectionInset.right - (self.columnsCount - 1) * self.columnMargin)/self.columnsCount; CGFloat height = [self.delegate waterflowLayout:self heightForWidth:width atIndexPath:indexPath]; // 计算位置 CGFloat x = self.sectionInset.left + (width + self.columnMargin) * [minColumn intValue]; CGFloat y = [self.maxYDict[minColumn] floatValue] + self.rowMargin; // 更新这一列的最大Y值 self.maxYDict[minColumn] = @(y + height); // 创建属性 UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; attrs.frame = CGRectMake(x, y, width, height); return attrs;}/** * 返回rect范围内的布局属性 */- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect{ return self.attrsArray;}@end
2.控制器如何使用?
//// ViewController.m// 0104-瀑布流#import "ViewController.h"#import "WaterflowLayout.h"#import "ShopCell.h"#import "MJExtension.h"#import "Shop.h"#import "MJRefresh.h"@interface ViewController ()<UICollectionViewDataSource,UICollectionViewDelegate,WaterflowLayoutDelegate>@property(nonatomic,weak)UICollectionView *collectionView;@property(nonatomic,strong)NSMutableArray *shops;@end@implementation ViewControllerstatic NSString *const ID = @"shop";- (NSMutableArray *)shops{ if (_shops == nil) { self.shops = [NSMutableArray array]; //2.加载1.plist创建模型 NSArray *shopArray = [Shop objectArrayWithFilename:@"1.plist"]; [self.shops addObjectsFromArray:shopArray]; } return _shops; }- (void)viewDidLoad { [super viewDidLoad]; //1.创建UICollectionView [self createCollectionView]; //2.添加一个上来刷新尾部控件(MJRefresh) [self.collectionView addFooterWithTarget:self action:@selector(loadMoreShops)];}/** * 加载更多商品 */- (void)loadMoreShops{ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSArray *shopArray = [Shop objectArrayWithFilename:@"1.plist"]; [self.shops addObjectsFromArray:shopArray]; [self.collectionView reloadData]; [self.collectionView footerEndRefreshing]; });}/** * 创建UICollectionView */- (void)createCollectionView{ WaterflowLayout *layout = [[WaterflowLayout alloc] init]; layout.delegate = self;// layout.sectionInset = UIEdgeInsetsMake(100, 20, 40, 30);// layout.columnMargin = 20;// layout.rowMargin = 30;// layout.columnsCount = 4; UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout]; collectionView.delegate = self; collectionView.dataSource = self; [collectionView registerNib:[UINib nibWithNibName:@"ShopCell" bundle:nil] forCellWithReuseIdentifier:ID]; [self.view addSubview:collectionView]; self.collectionView = collectionView;}#pragma mark - UICollectionViewDataSource/** * 每组有多少个cell */- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{ return self.shops.count;}/** * 返回cell */- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{ ShopCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:ID forIndexPath:indexPath]; cell.shop = self.shops[indexPath.item]; return cell;}#pragma mark - UICollectionViewDelegate- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{ NSLog(@"点击了第%ld个cell",(long)indexPath.item); }#pragma mark - WaterflowLayoutDelegat- (CGFloat)waterflowLayout:(WaterflowLayout *)waterflowLayout heightForWidth:(CGFloat)width atIndexPath:(NSIndexPath *)indexPath{ Shop *shop = self.shops[indexPath.item]; return shop.h / shop.w * width;}@end3. 自定义的UICollectionViewCell
//// ShopCell.h// 0104-瀑布流#import <UIKit/UIKit.h>@class Shop;@interface ShopCell : UICollectionViewCell@property(nonatomic,strong)Shop *shop;@end
//// ShopCell.m// 0104-瀑布流#import "ShopCell.h"#import "Shop.h"#import "UIImageView+WebCache.h"@interface ShopCell()@property (weak, nonatomic) IBOutlet UIImageView *imageView;@property (weak, nonatomic) IBOutlet UILabel *priceLabel;@end@implementation ShopCell/* iOS9 HTTP 不能正常使用的解决办法: 1.在Info.plist中添加NSAppTransportSecurity类型Dictionary。 2.在NSAppTransportSecurity下添加NSAllowsArbitraryLoads类型Boolean,值设为YES */- (void)setShop:(Shop *)shop{ _shop = shop; // 1.图片 [self.imageView sd_setImageWithURL:[NSURL URLWithString:shop.img] placeholderImage:[UIImage imageNamed:@"loading"]]; // 2.价格 self.priceLabel.text = shop.price;}- (void)awakeFromNib { // Initialization code}@end
4.cell上用到的模型
//// Shop.h#import <UIKit/UIKit.h>@interface Shop : NSObject@property (nonatomic, assign) CGFloat w;@property (nonatomic, assign) CGFloat h;@property (nonatomic, copy) NSString *img;@property (nonatomic, copy) NSString *price;@end
//// shop.m#import "Shop.h"@implementation Shop@end5.1.plist数据结构,实际开发中应该是去服务器获取数据
0 0
- 自定义UICollectionViewLayout—实现瀑布流效果
- 自定义UICollectionViewLayout实现瀑布流
- iOS自定义UICollectionViewLayout布局实现瀑布流
- 自定义UICollectionViewLayout之瀑布流
- Objectiv-c - UICollectionViewLayout自定义布局-瀑布流
- 使用UICollectionView 重写UICollectionViewLayout实现瀑布流
- iOS开发进阶 - 自定义UICollectionViewLayout实现瀑布流布局
- 瀑布流UICollectionViewFlowLayout/UICollectionViewLayout
- 自定义ViewGroup实现瀑布流效果
- 自定义UICollectionViewLayout(原形环绕效果)
- 自定义实现带文字标题的瀑布流效果
- UICollectionViewLayout的简单使用(简单瀑布流)
- android 瀑布流实现效果
- 瀑布流效果怎么实现
- staggeredGridView 实现瀑布流效果
- RecycleView 实现瀑布流效果
- JavaScript实现瀑布流效果
- RecyclerView 实现瀑布流效果
- Java温习(1)
- Objective - C UIActionSheet 图片相关 将选中图片放在指定位置并适应大小,长按保存
- linux下查找命令的使用:find、locate、whereis、grep、which
- java 反射机制 / 反射new 对象 / 反射方式调用方法
- bzoj1857 传送带 三分
- 自定义UICollectionViewLayout—实现瀑布流效果
- iOS开发~CocoaPods使用详细说明
- JSP页面工作原理
- ZOJ1067
- labview 异步调用VI
- 安卓点点滴滴-------ListView和ScrollView的冲突问题
- final,finally,finalize的区别?
- Java概述
- 3268最短路问题