//=========================================.h=================================
// TopBarLayout.h
// LOLADFNeverGiveUp
//
// Created by 曹老师 on 2018/12/17.
// Copyright © 2018 All rights reserved.
//
#import
NS_ASSUME_NONNULL_BEGIN
@interface ZoneImageFlowLayout : UICollectionViewFlowLayout
// item 的行距(默认4.0)
@property (nonatomic, assign) CGFloat lineSpacing;
// item 的间距 (默认4.0)
@property (nonatomic, assign) CGFloat interitemSpacing;
// header 高度(默认0.0)
@property (nonatomic, assign) CGFloat headerViewHeight;
// footer 高度(默认0.0)
@property (nonatomic, assign) CGFloat footerViewHeight;
// item 高度 (默认30)
@property (nonatomic, assign) CGFloat itemHeight;
// footer 边距缩进(默认UIEdgeInsetsZero)
@property (nonatomic, assign) UIEdgeInsets footerInset;
// header 边距缩进(默认UIEdgeInsetsZero)
@property (nonatomic, assign) UIEdgeInsets headerInset;
// item 边距缩进(默认UIEdgeInsetsZero)
@property (nonatomic, assign) UIEdgeInsets itemInset;
@end
NS_ASSUME_NONNULL_END
//============================================.m==========================
//
// TopBarLayout.m
// LOLADFNeverGiveUp
//
// Created by 曹老师 on 2018/12/17.
// Copyright © 2018 All rights reserved.
//
#import "ZoneImageFlowLayout.h"
@interface ZoneImageFlowLayout()
/** 总的布局对象数组,包括item,sectionHeader,footerHeader */
@property (nonatomic, strong) NSMutableArray *attributesArray;
/** item的布局对象数组 */
@property (nonatomic, strong) NSMutableArray *itemsattributes;
/** header的布局对象数组 */
@property(nonatomic,strong)NSMutableArray*headerAttributes;
/** footer的布局对象数组 */
@property(nonatomic,strong)NSMutableArray*footerAttributes;
/** 计算 collectionview 的内容高度 */
@property (nonatomic, assign) CGFloat contentHeight;
/** 计算 collectionview 的内容宽度 */
@property (nonatomic, assign) CGFloat contentWidth;
/** collectionview 自身的宽度 */
@property (nonatomic, assign) CGFloat viewWidth;
@end
@implementationZoneImageFlowLayout
#pragma mark - initialize
- (instancetype)init {
if(self= [superinit]) {
//设置间距的默认值
self.headerViewHeight = 0.0;
self.footerViewHeight = 0.0;
self.interitemSpacing = 4.0;
self.lineSpacing=4.0;
self.itemHeight= (kScreenWidth-48) /3;
self.itemInset = UIEdgeInsetsZero;
self.headerInset = UIEdgeInsetsZero;
self.footerInset = UIEdgeInsetsZero;
}
return self;
}
/** 1、当collectionView布局item时 第一个执行的方法 */
- (void)prepareLayout {
/** 重写layout中的方法 首先必须调用父类 */
[superprepareLayout];
self.viewWidth =self.collectionView.bounds.size.width -self.itemInset.left -self.itemInset.right;
//所有内容的布局属性数组
self.attributesArray = [NSMutableArray array];
//item的数据模型是2原数组,就是第一层数组包含的是section,第二层是每个section包含的item
self.itemsattributes = [NSMutableArray array];
//记录 collectionview 的内容高度
self.contentHeight =0.0;
self.contentWidth =0.0;
/** 获取collectionView 中的item的个数 */
NSInteger sectionCount = [self.collectionView numberOfSections];
/** 遍历得到每个item 设置位置信息 */
for(NSInteger i =0; i < sectionCount; i++) {
NSInteger itemCount = [self.collectionView numberOfItemsInSection:i];
for(NSInteger j =0; j < itemCount; j++) {
[selfsetItemFrameWithIndexPath:[NSIndexPath indexPathForItem:j inSection:i]];
if( (i == sectionCount -1) && ( j == itemCount -1) ) {
//这里是当最后一个 item 的 layoutAttributes 设置完成后如果有设置 footer 就要把 footer 添加到所有 layoutAttributes 数组
// if ( [(NSObject *)self.delegate respondsToSelector:@selector(collectionViewDynamicFooterSizeWithIndexPath:)] ) {
//
// //获取最后一个 item 的 layoutAttributes
// UICollectionViewLayoutAttributes *lastAttributes = self.attributesArray.lastObject;
// //添加 footer 的 layoutAttributes
// [self makeFooterAttributesWithLastItemAttributes:lastAttributes];
//
// // 获取新添加的 footer 的 layoutAttributes
// UICollectionViewLayoutAttributes *footerAttributes = self.footerAttributes.lastObject;
// //计算总高度
// self.contentHeight = CGRectGetMaxY(footerAttributes.frame) + self.itemInset.bottom;
// }
}
}
}
}
- (void)setItemFrameWithIndexPath:(NSIndexPath *)indexPath {
//这里主要是设置一下 item 的初始 frame
CGFloat x =0.0;
CGFloat y =0.0;
CGFloat width = (kScreenWidth -48) /3;
// 获取数组最后一个 layoutAttributes, 这样方便计算 frame 和 判断是否需要计算新的 section
UICollectionViewLayoutAttributes *lastAttributes =self.attributesArray.lastObject;
if( lastAttributes ) {
//如果数组有值代表不是设置第一个item
if( lastAttributes.indexPath.section == indexPath.section ) {
//同一组
if( (CGRectGetMaxX(lastAttributes.frame) +self.interitemSpacing + width >self.viewWidth) &&
(self.scrollDirection == UICollectionViewScrollDirectionVertical)) {
//需要换行
x =self.itemInset.left;
y = CGRectGetMaxY(lastAttributes.frame) +self.lineSpacing;
}else{
//不需要换行
x = CGRectGetMaxX(lastAttributes.frame) +self.interitemSpacing;
y = CGRectGetMinY(lastAttributes.frame);
}
}else{
//不同一组
//添加 footer 的布局,内部会判断是否需要添加
[selfmakeFooterAttributesWithLastItemAttributes:lastAttributes];
//添加一个新的 section 数组
[self.itemsattributes addObject:[NSMutableArray array]];
//这里重新获取最后一个 layoutAttributes 是因为如果加入了 footer 总的 layoutAttributes就会改变
lastAttributes =self.attributesArray.lastObject;
//添加 header 的布局,内部会判断是否需要添加
[selfmakeHeaderAttributesWithIndexPath:indexPath lastItemAttributes:lastAttributes];
//设置新的 section 的第一个 item 的 frame
x =self.itemInset.left;
y = CGRectGetMaxY(lastAttributes.frame) +self.lineSpacing *2+self.headerViewHeight;
}
}else{
//这里是设置第一个section的item
[self.itemsattributes addObject:[NSMutableArray array]];
//添加 header 的布局,内部会判断是否需要添加
[selfmakeHeaderAttributesWithIndexPath:indexPath lastItemAttributes:lastAttributes];
//这里判断是否有 header, 如果有就获取最后一个 layoutAttributes
if(self.headerAttributes.count ) {
lastAttributes =self.attributesArray.lastObject;
}
//设置新的 section 的第一个 item 的 frame
x =self.itemInset.left;
y = lastAttributes.size.height;
}
//设置每一个 item 的 frame
UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
/** 添加frame */
attributes.frame = CGRectMake(x, y, width, width);
self.contentHeight = CGRectGetMaxY(attributes.frame) +self.lineSpacing;
self.contentWidth = CGRectGetMaxX(attributes.frame) +self.interitemSpacing;
/** 保存在数组中 */
[self.itemsattributes[indexPath.section] addObject:attributes];
[self.attributesArray addObject:attributes];
}
#pragma mark - New Header Or Footer
- (void)makeHeaderAttributesWithIndexPath:(NSIndexPath *)indexPath lastItemAttributes:(UICollectionViewLayoutAttributes *)attributes {
//设置第一个section的header
UICollectionViewLayoutAttributes *headerAttributes = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader withIndexPath:indexPath];
CGFloat y = (attributes)?CGRectGetMaxY(attributes.frame) +self.lineSpacing:self.itemInset.top;
CGFloat headerWidth = 0.0;
CGFloat headerHeight = 0.0;
// if ( [(NSObject *)self.delegate respondsToSelector:@selector(collectionViewDynamicHeaderSizeWithIndexPath:)] ) {
// CGSize size = [self.delegate collectionViewDynamicHeaderSizeWithIndexPath:indexPath];
//
// headerWidth = size.width;
// headerHeight = size.height;
// }else {
// headerWidth = kScreenWidth - self.headerInset.left - self.headerInset.right;
// headerHeight = self.headerViewHeight;
// }
if( headerHeight >0.0) {
headerAttributes.frame = CGRectMake(self.headerInset.left, y, headerWidth, headerHeight);
[self.headerAttributes addObject:headerAttributes];
[self.attributesArray addObject:headerAttributes];
}
}
- (void)makeFooterAttributesWithLastItemAttributes:(UICollectionViewLayoutAttributes*)attributes {
UICollectionViewLayoutAttributes *footerAttributes = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionFooter withIndexPath:attributes.indexPath];
CGFloatfooterWidth = 0.0;
CGFloatfooterHeight = 0.0;
// if ( [(NSObject *)self.delegate respondsToSelector:@selector(collectionViewDynamicFooterSizeWithIndexPath:)] ) {
//
// CGSize size = [self.delegate collectionViewDynamicFooterSizeWithIndexPath:attributes.indexPath];
// footerWidth = size.width;
// footerHeight = size.height;
// } else {
// footerWidth = kScreenWidth - self.footerInset.left - self.footerInset.right;
// footerHeight = self.footerViewHeight;
// }
if( footerHeight >0) {
footerAttributes.frame=CGRectMake(self.footerInset.left,CGRectGetMaxY(attributes.frame) +self.lineSpacing, footerWidth, footerHeight);
[self.footerAttributesaddObject:footerAttributes];
[self.attributesArrayaddObject:footerAttributes];
}
}
#pragma mark - 布局
//这个是返回所有 header, footer, item 属性的回调方法, 一定要实现
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
return self.attributesArray;
}
- (UICollectionViewLayoutAttributes*)layoutAttributesForItemAtIndexPath:(NSIndexPath*)indexPath {
returnself.itemsattributes[indexPath.section][indexPath.item];
}
- (UICollectionViewLayoutAttributes*)layoutAttributesForSupplementaryViewOfKind:(NSString*)elementKind atIndexPath:(NSIndexPath*)indexPath {
if ( [elementKind isEqual: UICollectionElementKindSectionHeader] ) {
returnself.headerAttributes[indexPath.section];
}else{
returnself.footerAttributes[indexPath.section];
}
}
/** 4、设置滚动范围 */
// 这里可以处理 uicollectionview 内容不够屏幕高度不能滑动的问题,只要把 contentsize.height 设置成比屏幕高度大就可以了
- (CGSize)collectionViewContentSize {
if (self.scrollDirection == UICollectionViewScrollDirectionHorizontal) {
return CGSizeMake(self.contentWidth + self.itemInset.right, 0.0);
}else{
return CGSizeMake(0.0, self.contentHeight + self.itemInset.bottom);
}
}
#pragma mark - LazyLoad
// header 的布局属性数组
- (NSMutableArray*)headerAttributes {
if ( !_headerAttributes ) {
_headerAttributes = [NSMutableArray array];
}
return _headerAttributes;
}
// footer 的布局属性数组
- (NSMutableArray*)footerAttributes {
if ( !_footerAttributes ) {
_footerAttributes = [NSMutableArray array];
}
return _footerAttributes;
}
@end
网友评论