iOS横向瀑布流的封装
前段时间, 做一个羡慕, 需要使用到瀑布流! 说道瀑布流, 或许大家都不陌生, 瀑布流的实现也有很多种! 从scrollView 到 tableView 书写的瀑布流, 然后再到2012年iOS6 苹果API 新加进的collectionView进行的瀑布流封装! 确实, 不论是写起来还是用起来都要方便很多!
由于项目开发中需要使用到很像瀑布流, 本来想着懒省事, 直接搜一个第三方, 可搜了一会, 并没有搜到有关横向瀑布流的第三方! 于是就决定自己写一个吧! 里边用到的就是UICollecitionViewFlowLayout 的一个UICollectionViewLayoutAttributes 这个属性!
要明白瀑布流的原理, 写起来就会方便很多! 我下代码, 就是喜欢加多注释, 能够方便自己去找问题, 也能把当时的思路给记下来! 所以, 代码看起来, 好多绿色的中文注释, 或许对大神来说, 很弱! 但是, 能然自己读懂, 让大家读懂就够了!哈哈, 废话不多说! 直接上代码了! 思路还有实现步骤全在代码里!
.h 生命中只需要传入一个 你所需要横向瀑布流的行数, 还有一个model类的数组, model类是你自己定义的, 里边有图片的宽高,就可以了!
有什么疑问, 或者写的不对的地方, 希望提出来, 我虚心学习, 向大家探讨探讨
//
// JF HorizontalWaterFlowLayout.h
// ArtWorld
//
// Created by laouhn on 15/10/29.
// Copyright © 2015年 Jesonliu. All rights reserved.
// #import <UIKit/UIKit.h> @interface JF_HorizontalWaterFlowLayout : UICollectionViewFlowLayout // 总行数
@property (nonatomic, assign) NSInteger rowCount;
// 商品数据数组
@property (nonatomic, strong) NSArray *modelList; @end
//
// JF HorizontalWaterFlowLayout.m
// ArtWorld
//
// Created by laouhn on 15/10/29.
// Copyright © 2015年 Jesonliu. All rights reserved.
// #import "JF HorizontalWaterFlowLayout.h"
#import "ArtCollectionViewCellModel.h" @interface JF_HorizontalWaterFlowLayout ()
@property (nonatomic, assign) CGFloat remmenberW; // 所有item的属性的数组
@property (nonatomic, strong) NSArray *layoutAttributesArray; // 定义布局属性的数组, 用来存放布局item 的属性 @end @implementation JF_HorizontalWaterFlowLayout
/**
* 布局准备方法 当collectionView的布局发生变化时 会被调用
* 通常是做布局的准备工作 itemSize.....
* UICollectionView 的 contentSize 是根据 itemSize 动态计算出来的
*/ - (void)prepareLayout {
[super prepareLayout];
// 根据行数 计算item的高度 所有item 的高度是一样的
// 内容页的高度
CGFloat contenHeight = self.collectionView.bounds.size.height - self.sectionInset.top - self.sectionInset.bottom;
// 行与行之间的距离
CGFloat marginY = self.minimumLineSpacing;
// item 的高度
CGFloat itemHeight = (contenHeight - marginY * (self.rowCount - )) / self.rowCount;
// 计算布局属性
[self computeAttributesWithItemWith:itemHeight];
} /**
根据itemHeight 计算布局属性
*/
- (void)computeAttributesWithItemWith:(CGFloat)itemHeight {
// 定义一个行宽数组 记录每一行的总宽度
CGFloat rowWidth[self.rowCount];
// 定义一个记录每一行的总item个数数组
NSInteger rowItemCount[self.rowCount]; // 此处为C语言格式, 定义两个数组, 元素个数为self.rowCount, 数组类型为CGFloat 和 NSInteger // 初始化
for (int i = ; i < self.rowCount; i++) {
rowWidth[i] = self.sectionInset.left; // 行宽 要加上分区距离左边的距离 所以初始距离 只有分区距左边的距离
rowItemCount[i] = ; // 初始化时, 是每一行item 的个数为零, 清空数组元素内容
} // 遍历modelList 数组, 计算相关属性
NSInteger index = ; // 定义索引变量, 初始值为零 NSMutableArray *attributesArray = [NSMutableArray arrayWithCapacity:self.modelList.count]; // 定义一个可变存储布局属性的数组, 并开辟空间大小为self.modelList.count个空间 // 遍历self.modelList 数组, 得到model 类, 获取属性
for (ArtCollectionViewCellModel *model in self.modelList) { // 创建路径, 记录item 所在分区分区和位置
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:]; // 根据路径创建对应的布局属性
UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; // 找出最短的行号
NSInteger row = [self shortestRow:rowWidth]; // 追加在最短行, 使记录每一行的总item个数数组中最短行对应的元素个数 +1
rowItemCount[row]++; // X值
CGFloat itemX = rowWidth[row]; // 最短行的总宽度 // Y值
CGFloat itemY = (itemHeight + self.minimumLineSpacing) * row + self.sectionInset.top; // 计算, 注意逻辑性 // 等比例缩放 计算item 的宽度
CGFloat itemW = ([model.worksWidth floatValue] / [model.worksHeight floatValue]) * itemHeight; // 显示宽 / 显示高 = 实际宽 / 实际高
// 赋给布局属性的frame
attributes.frame = CGRectMake(itemX, itemY, itemW, itemHeight); // 添加到布局属性的数组中
[attributesArray addObject:attributes]; // 使列宽增加, 增量为item 自身的宽度, 加上两个item 之间的最小距离
rowWidth[row] += itemW + self.minimumInteritemSpacing; // 是索引+1
index++;
} // 找出 最宽行的行号
NSInteger row = [self widthestRow:rowWidth]; self.remmenberW = rowWidth[row]; // 根据最宽行设置itemSize 使用总宽度的平均值
CGFloat itemW = (rowWidth[row] - self.minimumInteritemSpacing * rowItemCount[row]) / rowItemCount[row]; self.itemSize = CGSizeMake(itemW, itemHeight); // 给属性数组设置数值
self.layoutAttributesArray = attributesArray.copy; } // 找出rowWidth 数组中最短行号 追加数据的时候 追加在最短行中
- (NSInteger)shortestRow:(CGFloat *)rowWidth {
CGFloat max = CGFLOAT_MAX;
NSInteger row = ;
for (int i = ; i < self.rowCount; i++) {
if (rowWidth[i] < max) {
max = rowWidth[i];
row = i;
}
}
return row; // 返回最短的行
} // 找出rowWidth 数组中最宽的行号
- (NSInteger)widthestRow:(CGFloat *)rowWidth {
CGFloat min = ;
NSInteger row = ;
for (int i = ; i < self.rowCount; i++) {
if (rowWidth[i] > min) {
min = rowWidth[i];
row = i;
}
}
return row;
} /**
* 跟踪效果:当到达要显示的区域时 会计算所有显示item的属性
* 一旦计算完成 所有的属性会被缓存 不会再次计算
* @return 返回布局属性(UICollectionViewLayoutAttributes)数组
*/
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { // 直接返回计算好的布局属性数组
return self.layoutAttributesArray;
} // 重写此方法, 改变collectionView的contentSize
- (CGSize )collectionViewContentSize{
return CGSizeMake(self.remmenberW, self.collectionView.bounds.size.height);
} @end
iOS横向瀑布流的封装的更多相关文章
- ios开发瀑布流框架的封装
一:瀑布流框架封装的实现思路:此瀑布流框架的封装仿照tableView的底层实现,1:每个cell的frame的设置都是找出每列的最大y值,比较每列的最大y值,将下一个cell放在最大y值最小的那一列 ...
- ios图片瀑布流代码
ios瀑布流,实现简单的瀑布流视图布局,可以显示网络图片,下拉刷新,上拉加载更多. 下载:http://www.huiyi8.com/sc/9087.html
- ios开发瀑布流框架的应用
一:瀑布流框架的应用:将封装好的瀑布流框架导入,遵守协议 二:代码: #import "HMShopsViewController.h" #import "HMShopC ...
- iOS基础 - 瀑布流
一.瀑布流简介 瀑布流,又称瀑布流式布局.是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部.最早采用此布局的网站是Pint ...
- iOS - UICollectionView 瀑布流 添加表头视图的坑
UICollectionView 瀑布流 添加表头视图的坑 首先是,需求加了个头视图在顶部,在collectionView中的头视图跟TableView的不一样,TableView的表头只要设置tab ...
- iOS开发瀑布流的实现
//自定义布局,继承于UICollectionViewLayout #import <UIKit/UIKit.h> @class WaterFlowLayout; @protocol W ...
- 用label实现横向瀑布流的方法
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAXcAAAKxCAIAAAAn+3udAAAKqWlDQ1BJQ0MgUHJvZmlsZQAASImVlg
- 飞流直下的精彩 -- 淘宝UWP中瀑布流列表的实现
在淘宝UWP中,搜索结果列表是用户了解宝贝的重要一环,其中的图片效果对吸引用户点击搜索结果,查看宝贝详情有比较大的影响.为此手机淘宝特意在搜索结果列表上采用了2种表现方式:一种就是普通的列表模式,而另 ...
- iOS 瀑布流封装
代码地址如下:http://www.demodashi.com/demo/12284.html 一.效果预览 功能描述:WSLWaterFlowLayout 是在继承于UICollectionView ...
随机推荐
- Java——类谜题
1.令人混淆的构造器 代码如下格式: public class Confusing { private Confusing(Object o) { System.out.println("O ...
- ASP.NET Security
<authentication mode="Forms"> <forms loginUrl="~/Account/Login" timeout ...
- isKindOfClass,isMemberOfClass使用备忘
isMemberOfClass 判断是否是属于这类的实例isKindOfClass 判断是否是这个类或者这个类的子类的实例 if ([teacher isKindOfClass:[Teacher cl ...
- HTML学习(五)链接
1.创建文本链接 <html> <body> <p> <a href="/index.html">本文本</a> 是一个 ...
- JAVA中传递参数乱码问题
url传递中文如果jsp页面,myeclipse.web.xml中org.springframework.web.filter.CharacterEncodingFilter,都是UTF-8编码,直接 ...
- 手动调用NDK编译HelloWorld
首先,你得有NDK(木有的自行搜索) /home/xxxx/tools/android-ndk-r12b 准备好你的HelloWorld程序源码: #include<stdio.h> in ...
- zeromq随笔
ZMQ (以下 ZeroMQ 简称 ZMQ)是一个简单好用的传输层,像框架一样的一个 socket library,他使得 Socket 编程更加简单.简洁和性能更高.是一个消息处理队列库,可在多个线 ...
- 【NOIP2015】反思+题解
D1T1> 神奇的幻方 模拟即可. #include <cstdio> #include <cstring> #include <algorithm> #de ...
- php包管理工具最基本的一些问题
windows下的 1.先安装windows下的set-up程序 点击一步步的, cmd进入,输入composer能成功显示一幅图说明安装成功 2.在下载,https://getcomposer.or ...
- JavaScript高级程序设计-8:BOM
1. 什么是BOM? BOM(Browser Object Mode) 是指浏览器对象模型,是用于描述这种对象与对象之间层次关系的模型,浏览器对象模型提供了独立于内容的.可以与浏览器窗口进行互动的对象 ...