/**
* 源代码链接
* 链接: 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 ;
} - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath]; cell.backgroundColor = [UIColor orangeColor]; NSInteger tag = ;
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 + arc4random_uniform();
}
//
//- (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 = ;//默认的列数
static const CGFloat LFDefaultColumnMargin = ;//每一列之间的间距
static const CGFloat LFDefaultRowMargin = ;//每一行之间的间距
static const UIEdgeInsets LFDefaultEdgeInsets = {,,,};//边缘间距 @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 = ; i < self.columnCount; i++) {
[self.columnHeights addObject:@(self.endgeInsets.top)];
} // 清除之前所有的布局属性
[self.attrsArray removeAllObjects]; // 开始创建每一个cell对应的布局属性
NSInteger count = [self.collectionView numberOfItemsInSection:]; for (NSInteger i = ;i < count;i++) {
// 创建位置
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:]; // 获取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 = ;
// 找出最小高度
CGFloat minColumnHeight = [self.columnHeights[] doubleValue];
for (NSInteger i = ; 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 - ) *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[] doubleValue];
for (NSInteger i = ; i < self.columnCount; i++) {
// 取出第i列的高度
CGFloat columnHeight = [self.columnHeights[i] doubleValue];
// 比较大小
if (maxColumnHeight < columnHeight) {
maxColumnHeight = columnHeight;
}
}
return CGSizeMake(, maxColumnHeight + self.endgeInsets.bottom);
} @end

iOS 瀑布流的基本原理的更多相关文章

  1. IOS 瀑布流UICollectionView实现

    IOS 瀑布流UICollectionView实现 在实现瀑布流之前先来看看瀑布流的雏形(此方法的雏形 UICollectionView) 对于UICollectionView我们有几点注意事项 它和 ...

  2. iOS 瀑布流之栅格布局

    代码地址如下:http://www.demodashi.com/demo/14760.html 一 .效果预览 二.确定需求 由下面的需求示意图可知模块的最小单位是正方形,边长是屏幕宽除去边距间隔后的 ...

  3. iOS 瀑布流封装

    代码地址如下:http://www.demodashi.com/demo/12284.html 一.效果预览 功能描述:WSLWaterFlowLayout 是在继承于UICollectionView ...

  4. IOS 瀑布流

    本篇博客应该算的上CollectionView的高级应用了,从iOS开发之窥探UICollectionViewController(一)到今天的(五),可谓是由浅入深的窥探了一下UICollectio ...

  5. iOS瀑布流实现(Swift)

    这段时间突然想到一个很久之前用到的知识-瀑布流,本来想用一个简单的方法,发现自己走入了歧途,最终只能狠下心来重写UICollectionViewFlowLayout.下面我将用两种方法实现瀑布流,以及 ...

  6. iOS 瀑布流的Demo

    /** * 瀑布流Demo的主要代码,若想看完整的代码请到下面链接去下载 * * 链接: https://pan.baidu.com/s/1slByAHB 密码: r3q6 */ #import &l ...

  7. ios 瀑布流的那些事情

    转载: 屎壳郎情调-成长日记 首先要知道:瀑布流的核心就是要获取到图片的长宽 网上的很多例子都是加载本地图片的 对于新手而言 改成加载网络图片的确是有点压力的  因为本地的图片 我们是很容易就能获取到 ...

  8. ios瀑布流

    http://blog.csdn.net/shenjx1225/article/details/9037631

  9. iOS开发笔记15:地图坐标转换那些事、block引用循环/weak–strong dance、UICollectionviewLayout及瀑布流、图层混合

    1.地图坐标转换那些事 (1)投影坐标系与地理坐标系 地理坐标系使用三维球面来定义地球上的位置,单位即经纬度.但经纬度无法精确测量距离戒面积,也难以在平面地图戒计算机屏幕上显示数据.通过投影的方式可以 ...

随机推荐

  1. nmap 高级扫描用法

    nmap提供了四项基本功能(主机发现.端口扫描.服务与版本侦测.OS侦测)及丰富的脚本库.Nmap既能应用于简单的网络信息扫描,也能用在高级.复杂.特定的环境中:例如扫描互联网上大量的主机:绕开防火墙 ...

  2. HDU 1176 经典dp

    记录最晚时间 从time为2枚举到最晚时间 每个时间段的x轴节点都等于上一个时间段的可触及的最大馅饼数 #include<stdio.h> #include<string.h> ...

  3. PHP 开发 APP 接口 学习笔记与总结 - APP 接口实例 [5] 版本设计分析及数据表设计

    APP 版本升级以及 APP 演示 ① 版本升级分析以及数据表设计 ② 版本升级接口开发以及 APP 演示 /** * version_upgrade 版本升级信息表 */ CREATE TABLE ...

  4. eclipse编译异常修正:the project cannot be built until its prerequisite...

    close错误的project,重新open , 再 clean下 .

  5. spotlight监控工具使用

    利用spotlight工具可以监控如下系统:        1.Spotlight on Unix 监控Linux服务器 1)安装 Spotlight on Unix 2)配置spotlight登陆用 ...

  6. Summary of java stream classes

    Java’s stream classes are good for streaming sequences of bytes, but they’re not good for streaming ...

  7. Charles辅助调试接口

    http://blog.sina.com.cn/s/blog_6ae8b50d0102w7tw.html

  8. Python基本数据类型之list列表

    列表是python中用的非常频繁的数据结构,它是有序序列.之前学的字符串就是一种有序序列.不过列表是可变的. 创建列表 li = list( )                          #构 ...

  9. Http响应code

    Http响应报文 HTTP响应也由三个部分组成,分别是:状态行.消息报头.响应正文. 其中,HTTP-Version表示服务器HTTP协议的版本:Status-Code表示服务器发回的响应状态代码:R ...

  10. SQL Server批量数据导出导入BCP使用

    BCP简介 bcp是SQL Server中负责导入导出数据的一个命令行工具,它是基于DB-Library的,并且能以并行的方式高效地导入导出大批量的数据.bcp可以将数据库的表或视图直接导出,也能通过 ...