iOS - UICollectionView 瀑布流 添加表头视图的坑
UICollectionView 瀑布流 添加表头视图的坑
首先是,需求加了个头视图在顶部,在collectionView中的头视图跟TableView的不一样,TableView的表头只要设置tableview.tableHeaderView就可以了. collectionView 怎么添加这样的效果的呢
有两种思路
第一种:在collectionView的段头代理中设置 (只在第一段中设置)
第二种:改变 collectionView 的内延距离, 然后添加在内延空白的位置.
第一种
// 返回头视图
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
UICollectionReusableView *reusableView =nil;
//返回段头段尾视图
if ([kind isEqualToString:UICollectionElementKindSectionHeader]) {
HMCollectionReusableView *header=[collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:headerViewIdentifier forIndexPath:indexPath];
//添加头视图的内容
header.backgroundColor = [UIColor redColor];
reusableView = header;
return reusableView;
}
//如果底部视图
if (kind ==UICollectionElementKindSectionFooter)
{
UICollectionReusableView *footerview = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"FooterView"forIndexPath:indexPath];
footerview.backgroundColor = [UIColor purpleColor];
reusableView = footerview; }
return reusableView;
}
但是你会发现,使用瀑布流的时候,,Cell都是不同大小的布局,UICollectionViewFlowLayout是自定义的布局,collectionView的代理不会走,所以,这里就比较坑了。
怎么解决呢 就是在自定义的Layout中添加加一个 Header类型的 UICollectionViewLayoutAttributes就可以。然后我把瀑布流的Cell的起始位置从headerView的最大Y开始布局。这样设置之后,controllerView中的代理方法才会走,要记得注册头视图哦,不然会崩。
注册段头
//注册段头部视图
[collectionView registerClass:[HMCollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:headerViewIdentifier];
//xib
[collectionView registerNib:[UINib nibWithNibName:@"HMCollectionReusableView" bundle:nil] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:headerViewIdentifier];
自定义的布局 HMWaterflowLayout : UICollectionViewLayout
.h
@interface HMWaterflowLayout : UICollectionViewLayout @property (nonatomic, assign) UIEdgeInsets sectionInset;
/** 段头的size */
@property (nonatomic, assign) CGSize headerReferenceSize; /** 每一列之间的间距 */
@property (nonatomic, assign) CGFloat columnMargin;
/** 每一行之间的间距 */
@property (nonatomic, assign) CGFloat rowMargin;
/** 显示多少列 */
@property (nonatomic, assign) int columnsCount; @property (nonatomic, weak) id<HMWaterflowLayoutDelegate> delegate; @end
.m
#import <UIKit/UIKit.h>
@class HMWaterflowLayout; @protocol HMWaterflowLayoutDelegate <NSObject>
- (CGFloat)waterflowLayout:(HMWaterflowLayout *)waterflowLayout heightForWidth:(CGFloat)width atIndexPath:(NSIndexPath *)indexPath;
@end#import "HMWaterflowLayout.h" @interface HMWaterflowLayout();
/** 这个字典用来存储每一列最大的Y值(每一列的高度) */
@property (nonatomic, strong) NSMutableDictionary *maxYDict; /** 存放所有的布局属性 */
@property (nonatomic, strong) NSMutableArray *attrsArray;
@end @implementation HMWaterflowLayout - (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 = ;
self.rowMargin = ;
self.sectionInset = UIEdgeInsetsMake(, , , );
self.columnsCount = ;
//如果段头的高度不一致 可以仿照UICollectionViewFlowLayout的代理 自己写一个代理方法返回 CGSize
self.headerReferenceSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, );
}
return self;
} - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
return YES;
} /**
* 每次布局之前的准备
*/
- (void)prepareLayout
{
[super prepareLayout]; // 1.清空最大的Y值
[self.maxYDict removeAllObjects]; for (int i = ; i<self.columnsCount; i++) {
NSString *column = [NSString stringWithFormat:@"%d", i];
self.maxYDict[column] = @(self.sectionInset.top);
} // 2.计算所有cell的属性
[self.attrsArray removeAllObjects]; //头部视图
UICollectionViewLayoutAttributes * layoutHeader = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader withIndexPath:[NSIndexPath indexPathWithIndex:]];
layoutHeader.frame =CGRectMake(,, self.headerReferenceSize.width, self.headerReferenceSize.height);
[self.attrsArray addObject:layoutHeader]; //item内容视图
NSInteger count = [self.collectionView numberOfItemsInSection:];
for (int i = ; i<count; i++) {
UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:]];
[self.attrsArray addObject:attrs];
}
} /**
* 返回所有的尺寸
*/
- (CGSize)collectionViewContentSize
{
__block NSString *maxColumn = @"";
[self.maxYDict enumerateKeysAndObjectsUsingBlock:^(NSString *column, NSNumber *maxY, BOOL *stop) {
if ([maxY floatValue] > [self.maxYDict[maxColumn] floatValue]) {
maxColumn = column;
}
}]; //包括段头headerView的高度
return CGSizeMake(, [self.maxYDict[maxColumn] floatValue] + self.sectionInset.bottom + self.headerReferenceSize.height );
} /**
* 返回indexPath这个位置Item的布局属性
*/
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
// 假设最短的那一列的第0列
__block NSString *minColumn = @"";
// 找出最短的那一列
[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 - ) * 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]; //把瀑布流的Cell的起始位置从headerView的最大Y开始布局
attrs.frame = CGRectMake(x, self.headerReferenceSize.height + y, width, height );
return attrs;
} /**
* 返回rect范围内的布局属性
*/
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
return self.attrsArray;
} @end
第二种
self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(, , , self.view.frame.size.height) collectionViewLayout:flowlayout];
self.collectionView.contentInset = UIEdgeInsetsMake(, , , );
UIImageView *imagev = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"015.png"]];
imagev.frame = CGRectMake(, -, , );
[self.collectionView addSubview: imagev];
[self.view addSubview: _collectionView];
提示: UICollectionReusableView 段头是可以自定义的 第一种比较好
注意:UITableView 有两个样式布局 1.Group 2.Plain (段头可以停留) 而UICollectionView 需要自己写布局 要想实现Plain (段头可以停留)的效果可以找一些网上的第三方的框架参考一下
iOS - UICollectionView 瀑布流 添加表头视图的坑的更多相关文章
- iOS横向瀑布流的封装
前段时间, 做一个羡慕, 需要使用到瀑布流! 说道瀑布流, 或许大家都不陌生, 瀑布流的实现也有很多种! 从scrollView 到 tableView 书写的瀑布流, 然后再到2012年iOS6 苹 ...
- ios图片瀑布流代码
ios瀑布流,实现简单的瀑布流视图布局,可以显示网络图片,下拉刷新,上拉加载更多. 下载:http://www.huiyi8.com/sc/9087.html
- ios开发瀑布流框架的应用
一:瀑布流框架的应用:将封装好的瀑布流框架导入,遵守协议 二:代码: #import "HMShopsViewController.h" #import "HMShopC ...
- ios开发瀑布流框架的封装
一:瀑布流框架封装的实现思路:此瀑布流框架的封装仿照tableView的底层实现,1:每个cell的frame的设置都是找出每列的最大y值,比较每列的最大y值,将下一个cell放在最大y值最小的那一列 ...
- UICollectionView瀑布流的实现原理(转)
http://ios.jobbole.com/85689/ 和使用 UIScollView 创刊一个瀑布流是一样的方式 7cc829d3gw1f4nq2oc09zj20j00hvq90.jpg 我的 ...
- iOS基础 - 瀑布流
一.瀑布流简介 瀑布流,又称瀑布流式布局.是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部.最早采用此布局的网站是Pint ...
- iOS开发瀑布流的实现
//自定义布局,继承于UICollectionViewLayout #import <UIKit/UIKit.h> @class WaterFlowLayout; @protocol W ...
- 【iOS开发】动态添加子视图 UIView 的正确方法
很多时候哥比较喜欢用代码添加视图,特别是要同时加很多UIView时,而且跟 xib 比起来代码更容易管理,在多人的项目中代码不容易 conflict. 但小牛哥最近发现很多新人都不太清楚正确的使用方法 ...
- 第二十九篇、UICollectionView瀑布流
1.实现思路 >第一种方案:UIScrollView 镶嵌三个UITableView (不推荐使用) >第二种方案:UIScrollView 镶嵌UIImageView (需要解决循环利用 ...
随机推荐
- discuz X论坛技术架构 MVC结构浅析
摘自:http://yeyuan.iteye.com/blog/930727 PS:本人刚接触discuz论坛,php水平有限,当中的理解,如有不正确之处,欢迎指出 ----------------- ...
- Cg入门10:Vertex Shader - 几何变换 —MVP矩阵变换
Unity内建矩阵类型: M:世界矩阵 V:摄像机矩阵 P:投影矩阵 T :矩阵的转置 IT : 转置的的逆 _Object2World: 模型到世界矩阵 _World2Object:世界到模型矩阵 ...
- zabbix 配置SNMP监控
什么是SNMP? 简单网络管理协议(SNMP),由一组网络管理的标准组成,包含一个应用层协议(application layer protocol).数据库模型(database schema)和一组 ...
- CentOS 7 打开关闭FirewallD防火墙端口命令
CentOS 7 使用firewalld代替了原来的iptables,使用方法如下: >>>关闭防火墙 systemctl stop firewalld.service ...
- thinkphp模板中使用方法
1.php中的方法使用 <?php $var_num = "13966778888"; $str = substr_replace($var_num,'*****',3,5) ...
- 软件设计模式之适配器模式(JAVA)
什么是适配器模式? 在计算机编程中,适配器模式(有时候也称包装样式或者包装)将一个类的接口适配成用户所期待的.适配器能将因为接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存 ...
- Linux下安装或升级Python 2.7
1.准备编译环境gcc 2.去官网下载要安装的对应版本的python的源代码 下载地址:https://www.python.org/downloads/source/ 你可以选择你要下载的版本,用w ...
- Line云端全自动加好友机器人
一个 LINE 帐号可以加入 5,000 名好友,让这些 5,000 名好友收到 LINE 的主动提醒,好友会看到我的头像.主页照片.姓名与状态消息等,这种行为称为 LINE 的曝光. 如果我们要针对 ...
- 使用pyinotify实现加强版的linux tail -f 命令,并且对日志类型的文本进行单独优化着色显示。
tail -f命令不能自动切换切片文件,例如日志是每100M生成一个新文件,tail -f不能自动的切换文件,必须关闭然后重新运行tail -f 此篇使用pyinotify,检测文件更新,并实现tai ...
- JBOSS 数据源配置并使用JNDI调用
-- 本文出自sleest (感谢yangjj ^_^) 场景分析: 某天系统的数据库维护方要求进行DG备库容灾演练,要把生产用RAC库模拟宕机并转移至DG备库上,由于是failover而不是swit ...