iOS-CollectionView 瀑布流视图
2016-06-30 17:16
447 查看
要做瀑布流,首先要清楚几点:
主要是对 UICollectionViewLayout 子类的编写。
第一步、自定义初始化(主要是参数的初始化,行数numberOfLine,行间距rowGap,列间距lineGap,边距sideGap)
第二步、prepareLayout(1.初始化每列高度的字典,2初始化属性数组。)
第三步、layoutAttributesForElementsInRect(返回属性数组。)
第四步、collectionViewContentSize (返回整个 collectionView 的尺寸。)
以下为源代码:
UICollectionViewLayout 子类 WaterLayout
// // WaterLayout.h // WaterFallLayout2 // // Created by zhengbing on 6/30/16. // Copyright © 2016 zhengbing. All rights reserved. // #import <UIKit/UIKit.h> //计算高度 typedef CGFloat(^HeightBlock)(NSIndexPath *indexPath, CGFloat width); @interface WaterLayout : UICollectionViewLayout @property(nonatomic, assign) NSInteger lineNumber; //每行个数 @property(nonatomic, assign) CGFloat rowGap; //行距(上下的距离) @property(nonatomic, assign) CGFloat lineGap; //列距(中间的距离) @property(nonatomic, assign) UIEdgeInsets sideGap; //边距 @property(nonatomic, copy) HeightBlock block; //计算cell 高度 -(instancetype)initWithLineNumber:(NSInteger)lineNumber rowGap:(CGFloat)rowGap lineGap:(CGFloat)lineGap sideGap:(UIEdgeInsets)sideGap; @end
// // WaterLayout.m // WaterFallLayout2 // // Created by zhengbing on 6/30/16. // Copyright © 2016 zhengbing. All rights reserved. // #import "WaterLayout.h" @interface WaterLayout() //1.存储每列高度的一个字典 @property(nonatomic, strong) NSMutableDictionary *dictOfLineHeight; //2.存储所有cell frame 的一个数组 @property(nonatomic, strong) NSMutableArray *arrayOfCellFrame; @end @implementation WaterLayout -(instancetype)initWithLineNumber:(NSInteger)lineNumber rowGap:(CGFloat)rowGap lineGap:(CGFloat)lineGap sideGap:(UIEdgeInsets)sideGap{ self = [super init]; if (self) { self.lineNumber = lineNumber; self.rowGap = rowGap; self.lineGap = lineGap; self.sideGap = sideGap; self.dictOfLineHeight = [NSMutableDictionary dictionary]; self.arrayOfCellFrame = [NSMutableArray array]; } return self; } //自动布局前的准备工作 - (void)prepareLayout{ //1.要把存储高度的字典补充值 for (NSInteger i = 0; i < _lineNumber; i++) { [self.dictOfLineHeight setObject:@(self.sideGap.top) forKey:[NSString stringWithFormat:@"%ld",i]]; } //2.把cell 的尺寸存进数组 NSInteger count = [self.collectionView numberOfItemsInSection:0]; for (NSInteger i=0; i<count; i++) { NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0]; [_arrayOfCellFrame addObject:[self layoutAttributesForItemAtIndexPath:indexPath]]; } } //返回所以cell frame 信息的数组 - (NSArray*)layoutAttributesForElementsInRect:(CGRect)rect{ return _arrayOfCellFrame; } //计算每个cell 的 frame 值 - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{ UICollectionViewLayoutAttributes *attr = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; //经过了逻辑处理,计算出了cell 的frame CGRect frame; CGFloat cellW = (self.collectionView.bounds.size.width - _sideGap.left - _sideGap.right - self.lineGap*(self.lineNumber - 1))/self.lineNumber; CGFloat cellH; if (self.block) { cellH = self.block(indexPath,cellW); } __block NSString *keyOfMinHeight = @"0"; [_dictOfLineHeight enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { if ([_dictOfLineHeight[keyOfMinHeight] floatValue] > [obj floatValue]) { keyOfMinHeight = key; } }]; NSInteger minHeiLineNumber = [keyOfMinHeight integerValue]; CGFloat pointX = (self.sideGap.left + minHeiLineNumber * (self.lineGap + cellW)); CGFloat pointY = [_dictOfLineHeight[keyOfMinHeight] floatValue]; frame = CGRectMake(pointX, pointY, cellW, cellH); //更新高度 _dictOfLineHeight[keyOfMinHeight] = @([_dictOfLineHeight[keyOfMinHeight] floatValue] + cellH + self.rowGap); attr.frame = frame; return attr; } //返回 集合视图的宽高 - (CGSize)collectionViewContentSize{ __block NSString *keyOfMaxHeight = @"0"; [_dictOfLineHeight enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { if ([_dictOfLineHeight[keyOfMaxHeight] floatValue] < [obj floatValue]) { keyOfMaxHeight = key; } }]; return CGSizeMake(self.collectionView.bounds.size.width, [_dictOfLineHeight[keyOfMaxHeight] floatValue]); } @end
MyCollectionViewCell 用 xib 定义的,里面放有一张添加好约束的图片。
// // MyCollectionViewCell.h // WaterFallLayout2 // // Created by zhengbing on 6/30/16. // Copyright © 2016 zhengbing. All rights reserved. // #import <UIKit/UIKit.h> @interface MyCollectionViewCell : UICollectionViewCell @property (weak, nonatomic) IBOutlet UIImageView *imageView; @property(nonatomic, strong) NSString* imageName; @end
// // MyCollectionViewCell.m // WaterFallLayout2 // // Created by zhengbing on 6/30/16. // Copyright © 2016 zhengbing. All rights reserved. // #import "MyCollectionViewCell.h" @implementation MyCollectionViewCell - (void)awakeFromNib { [super awakeFromNib]; // Initialization code } -(void)setImageName:(NSString *)imageName{ _imageView.image = [UIImage imageNamed:imageName]; } @end
DetailsViewController 展示瀑布流视图
// // DetailsViewController.m // WaterFallLayout2 // // Created by zhengbing on 6/30/16. // Copyright © 2016 zhengbing. All rights reserved. // #import "DetailsViewController.h" #import "MyCollectionViewCell.h" #import "WaterLayout.h" #define CELLID @"DetailsViewController" @interface DetailsViewController ()<UICollectionViewDelegate,UICollectionViewDataSource> @property(nonatomic, strong)NSMutableArray * dataSource; @property(nonatomic, strong)UICollectionView * collectionView; @end @implementation DetailsViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. [self initData]; [self initUI]; } -(void)initData{ _dataSource = [NSMutableArray array]; for (int i = 0; i < 20; i++) { NSString *imageName = [NSString stringWithFormat:@"%d",i+1]; [_dataSource addObject:imageName]; } } -(void)initUI{ self.view.backgroundColor = [UIColor yellowColor]; [self.view addSubview:self.collectionView]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } #pragma mark getter and setter -(UICollectionView *)collectionView{ if (!_collectionView) { //瀑布流布局 WaterLayout *layout = [[WaterLayout alloc] initWithLineNumber:3 rowGap:10 lineGap:10 sideGap:UIEdgeInsetsMake(10, 10, 10, 10)]; //block 回调,计算并返回每个 cell 图片的高度 layout.block = ^CGFloat(NSIndexPath *indexPath, CGFloat width){ UIImage *image = [UIImage imageNamed:_dataSource[indexPath.item]]; return (image.size.height/image.size.width)*width; }; _collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout]; _collectionView.delegate = self; _collectionView.dataSource = self; _collectionView.backgroundColor = [UIColor yellowColor]; [_collectionView registerNib:[UINib nibWithNibName:@"MyCollectionViewCell" bundle:[NSBundle mainBundle]] forCellWithReuseIdentifier:CELLID]; } return _collectionView; } #pragma mark delegate - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{ return _dataSource.count; } - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{ MyCollectionViewCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:CELLID forIndexPath:indexPath]; cell.imageName = _dataSource[indexPath.row]; return cell; } @end
相关文章推荐
- [iOS 禁用第三方输入法] 禁用第三方输入法+ExtensionPointIdentifier理解
- iOS 地图源及目的地定位、划线和系统导航的使用
- iOS开发 正则表达式
- ios开发解决遍历删除数组对象报错
- iOS 通过网址URL scheme传值
- NSMutableAttributedString属性文字
- ios pod库更新到1.0或1.0.1之正确修改podfile文件
- iOS中URL Scheme是干嘛的
- iOS-资源大全
- ios关于百度地图框架地理编码的封装;
- iOS 如何缩小包体的大小 (静态库,IPA)
- iOS开发 将某个视图置于某视图之上
- [iOS 文本输入限制]限制输入特定字符串等
- iOS容易造成循环引用的三种场景,就在你我身边!
- iOS 时间处理
- iOS 文字转化成图片
- 开源游戏“2048”IOS移植版
- 3分钟实现iOS语言本地化/国际化(图文详解)
- iOS的三种多线程技术 对比分析
- IOS StoryBoard 中 alpha设置 导致subview中的控件也透明了