iOS 瀑布流的基本原理
2016-08-31 16:46
337 查看
/** * 源代码链接 * 链接: https://pan.baidu.com/s/1nvLamEX 密码: kya5 */ #import <UIKit/UIKit.h> @interface AppDelegate : UIResponder <UIApplicationDelegate> @property (strong, nonatomic) UIWindow *window; @end
#import "AppDelegate.h" #import "RootViewController.h" @interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. self.window.backgroundColor = [UIColor whiteColor]; self.window.rootViewController = [[RootViewController alloc] init]; [self.window makeKeyAndVisible]; return YES; } @end
#import <UIKit/UIKit.h> @interface RootViewController : UIViewController @end
#import "RootViewController.h" #import "LFWaterfallLayout.h" @interface RootViewController ()<UICollectionViewDataSource,LFWaterfallLayoutDelegate> @end @implementation RootViewController static NSString *const identifier = @"waterfall"; - (void)viewDidLoad { [super viewDidLoad]; // 创建布局 LFWaterfallLayout *layout = [[LFWaterfallLayout alloc] init]; layout.delegate = self; // 创建collecView UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout]; collectionView.dataSource = self; [self.view addSubview:collectionView]; // 注册 [collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:identifier]; } #pragma mark -- UICollectionViewDataSource -- - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{ return 50; } - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{ UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath]; cell.backgroundColor = [UIColor orangeColor]; NSInteger tag = 10; UILabel *label = (UILabel *)[cell viewWithTag:tag]; if (!label) { label = [[UILabel alloc] init]; label.tag = tag; label.frame = cell.bounds; [cell.contentView addSubview:label]; } return cell; } #pragma mark -- LFWaterfallLayoutDelegate -- - (CGFloat)waterflowLayout:(LFWaterfallLayout *)waterflowLayout heightForItemAtIndex:(NSUInteger)index itemWidth:(CGFloat)itemWidth{ return 50 + arc4random_uniform(120); } // //- (CGFloat)columnCountInWaterflowLayout:(LFWaterfallLayout *)waterflowLayou{ // return 2; //} //- (CGFloat)columnMarginInWaterflowLayout:(LFWaterfallLayout *)waterflowLayout{ // return 20; //} //- (CGFloat)rowMarginInWaterflowLayout:(LFWaterfallLayout *)waterflowLayout{ // return 20; //} //- (UIEdgeInsets)edgeInsetsInWaterflowLayout:(LFWaterfallLayout *)waterflowLayout{ // return UIEdgeInsetsMake(20, 20, 20, 20); //} - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end
#import <UIKit/UIKit.h> @class LFWaterfallLayout; /** * 代理传值 */ @protocol LFWaterfallLayoutDelegate <NSObject> @required - (CGFloat)waterflowLayout:(LFWaterfallLayout *)waterflowLayout heightForItemAtIndex:(NSUInteger)index itemWidth:(CGFloat)itemWidth; @optional /** * 设置瀑布流的列数 */ - (CGFloat)columnCountInWaterflowLayout:(LFWaterfallLayout *)waterflowLayout; /** * 设置瀑布流列的间距 */ - (CGFloat)columnMarginInWaterflowLayout:(LFWaterfallLayout *)waterflowLayout; /** * 设置瀑布流行的间距 */ - (CGFloat)rowMarginInWaterflowLayout:(LFWaterfallLayout *)waterflowLayout; /** * 设置瀑布流边缘(四周)的间隙 */ - (UIEdgeInsets)edgeInsetsInWaterflowLayout:(LFWaterfallLayout *)waterflowLayout; @end @interface LFWaterfallLayout : UICollectionViewLayout @property (nonatomic , weak) id<LFWaterfallLayoutDelegate> delegate; @end
#import "LFWaterfallLayout.h" static const NSInteger LFDefaultColumnCount = 3;//默认的列数 static const CGFloat LFDefaultColumnMargin = 10;//每一列之间的间距 static const CGFloat LFDefaultRowMargin = 10;//每一行之间的间距 static const UIEdgeInsets LFDefaultEdgeInsets = {10,10,10,10};//边缘间距 @interface LFWaterfallLayout () /** * 存放所有cell的布局属性 */ @property (nonatomic , strong) NSMutableArray *attrsArray; /** * 存放所有列的当前高度 */ @property (nonatomic , strong) NSMutableArray *columnHeights; - (CGFloat)rowMargin; - (CGFloat)columnMargin; - (NSInteger)columnCount; - (UIEdgeInsets)endgeInsets; @end @implementation LFWaterfallLayout #pragma mark -- 数据处理 -- - (CGFloat)rowMargin{ if ([self.delegate respondsToSelector:@selector(rowMarginInWaterflowLayout:)]) { return [self.delegate rowMarginInWaterflowLayout:self]; }else{ return LFDefaultRowMargin; } } - (CGFloat)columnMargin{ if ([self.delegate respondsToSelector:@selector(columnMarginInWaterflowLayout:)]) { return [self.delegate columnMarginInWaterflowLayout:self]; }else{ return LFDefaultColumnMargin; } } - (UIEdgeInsets)endgeInsets{ if ([self.delegate respondsToSelector:@selector(edgeInsetsInWaterflowLayout:)]) { return [self.delegate edgeInsetsInWaterflowLayout:self]; }else{ return LFDefaultEdgeInsets; } } - (NSInteger)columnCount{ if ([self.delegate respondsToSelector:@selector(columnCountInWaterflowLayout:)]) { return [self.delegate columnCountInWaterflowLayout:self]; }else{ return LFDefaultColumnCount; } } - (NSMutableArray *)attrsArray{ if (!_attrsArray) { _attrsArray = [NSMutableArray array]; } return _attrsArray; } - (NSMutableArray *)columnHeights{ if (!_columnHeights) { _columnHeights = [NSMutableArray array]; } return _columnHeights; } /** * 初始化 */ - (void)prepareLayout{ [super prepareLayout]; // 清除以前计算的所有高度 [self.columnHeights removeAllObjects]; for (NSInteger i = 0; i < self.columnCount; i++) { [self.columnHeights addObject:@(self.endgeInsets.top)]; } // 清除之前所有的布局属性 [self.attrsArray removeAllObjects]; // 开始创建每一个cell对应的布局属性 NSInteger count = [self.collectionView numberOfItemsInSection:0]; for (NSInteger i = 0 ;i < count;i++) { // 创建位置 NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0]; // 获取indexPath位置对应cell的属性 UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:indexPath]; [self.attrsArray addObject:attributes]; } } /** * 决定cell的布局 */ - (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{ return self.attrsArray; } /** * 返回indexPath位置cell对应的布局属性 */ - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{ // 创建布局属性 UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; //collectionView的宽度 CGFloat collectionViewWidth = self.collectionView.frame.size.width; // 找出高度最短的那一列 NSInteger shortestColumn = 0; // 找出最小高度 CGFloat minColumnHeight = [self.columnHeights[0] doubleValue]; for (NSInteger i = 1 ; i < self.columnCount; i++) { // 取出第i列的高度 CGFloat columnHeight = [self.columnHeights[i] doubleValue]; // 比较大小 if (minColumnHeight > columnHeight) { minColumnHeight = columnHeight; shortestColumn = i; } } // 宽度 CGFloat width = (collectionViewWidth - self.endgeInsets.left - self.endgeInsets.right - (self.columnCount - 1) *self.columnMargin) / self.columnCount; // x坐标 CGFloat x = self.endgeInsets.left + shortestColumn * (width + self.columnMargin); // y坐标 CGFloat y = minColumnHeight; if (y != self.endgeInsets.top) { y += self.rowMargin; } // 高度 CGFloat height = [self.delegate waterflowLayout:self heightForItemAtIndex:indexPath.item itemWidth:width]; //设置布局属性的frame attributes.frame = CGRectMake(x,y, width, height); // 更新高度 self.columnHeights[shortestColumn] = @(CGRectGetMaxY(attributes.frame)); return attributes; } - (CGSize)collectionViewContentSize{ // 找出最大高度 CGFloat maxColumnHeight = [self.columnHeights[0] doubleValue]; for (NSInteger i = 1 ; i < self.columnCount; i++) { // 取出第i列的高度 CGFloat columnHeight = [self.columnHeights[i] doubleValue]; // 比较大小 if (maxColumnHeight < columnHeight) { maxColumnHeight = columnHeight; } } return CGSizeMake(0, maxColumnHeight + self.endgeInsets.bottom); } @end
相关文章推荐
- iOS 知识 - 常用小技巧大杂烩
- 自定义iOS7导航栏背景,标题和返回按钮文字颜色
- iOS 杂笔-如何解决tableview显示错乱问题
- IOS 静态库制作
- iOS中按行读取txt格式的数据
- 李洪强iOS开发之通知的使用
- [iOS IPV6被拒] 坑坑坑
- iOS开发Quartz2D之十二:手势解锁实例
- iOS开发Quartz2D十二:手势解锁实例
- IOS 那些设计模式,持续更新中...
- CocoaPods安装应用和坑
- iOS简单易用的标签列表界面
- ios内存优化
- IOS开发基础知识--碎片47
- iOS网路传输zip压缩
- ios 自定义返回按钮侧滑失效完美解决方案
- [置顶] iOS 常用加密
- iOS--js和oc交互
- IOS跳转其他应用方法
- iOS编译报错之directory not found for option XXX