在常见的UI布局中,往往会含有广告栏banner,按钮,商品信息展示等等元素。例如如下的布局格式
其解决方式优先想到的是采用瀑布流自定义布局去实现类似的布局格式
自定义CollectionViewLayout
自定义CollectionViewLayout需要去实现如下的基础方法
1、prepareLayout预先布局方法
2、collectionViewContentSize 返回collectionView的内容尺寸方法
3、layoutAttributesForElementsInRect:(CGRect)rect 返回可见范围内的所有布局
4、layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath 返回某个item的布局属性
5、layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath 返回附加视图的布局属性
下面直接上代码去实现类似上图的多分组多列的不规则布局
自定义CollectionViewLayout,方法声明文件
#import <UIKit/UIKit.h>
@class CLCollectionViewLayout;
//MARK: 代理方法
@protocol CLCollectionViewLayoutDataSource<NSObject>
@required
/**根据每一个分组返回每个分组中含有多少列数*/
- (NSInteger)collectionView:(UICollectionView *)collectionView layout:(CLCollectionViewLayout *)layout numberOfColumnInSection:(NSInteger)section;
/**返回每一列的高度*/
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(CLCollectionViewLayout *)layout itemHeight:(CGFloat)height heightForItemAtIndexPath:(NSIndexPath *)indexPath;
@optional
/**返回item之间的行间距*/
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(CLCollectionViewLayout *)layout minimumLineSpacingForSectionAtIndex:(NSInteger)section;
/**返回item之间的列间距*/
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(CLCollectionViewLayout *)layout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section;
/**返回每个section附件视图的内容偏移尺寸*/
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(CLCollectionViewLayout *)layout insetForSectionAtIndex:(NSInteger)section;
/**返回header的高度*/
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(CLCollectionViewLayout *)layout referenceHeightForHeaderInSection:(NSInteger)section;
/**返回footer的高度*/
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(CLCollectionViewLayout *)layout referenceHeightForFooterInSection:(NSInteger)section;
@end
@interface CLCollectionViewLayout : UICollectionViewLayout
/*
@ dataSource 代理属性
@ minimumLineSpacing 最小行间距
@ minimumInteritemSpacing 最小列间距
@ sectionHeadersPinToVisibleBounds sessionHeader是否可滚动,默认可以滚动
*/
@property (nonatomic,weak) id <CLCollectionViewLayoutDataSource> dataSource;
@property (nonatomic,assign) CGFloat minimumLineSpacing;
@property (nonatomic,assign) CGFloat minimumInteritemSpacing;
@property (nonatomic,assign) BOOL sectionHeadersPinToVisibleBounds;
@end
方法实现文件如下
1、创建私有分类
@interface CLCollectionViewLayout()
@property (nonatomic, strong)
/*属性数组*/
NSMutableArray<NSMutableArray<UICollectionViewLayoutAttributes *> *> *itemLayoutAttributes;
@property (nonatomic, strong) NSMutableArray<UICollectionViewLayoutAttributes *> *headerLayoutAttributes;
@property (nonatomic, strong) NSMutableArray<UICollectionViewLayoutAttributes *> *footerLayoutAttributes;
/*sessionHeader数组*/
@property (nonatomic, strong) NSMutableArray<NSNumber *> *heightOfSections;
@property (nonatomic, assign) CGFloat contentHeight;
@property (strong, nonatomic) NSMutableArray *shouldanimationArr;
@end
2、数据与集合的初始化
-(void)initData {
self.contentHeight = 0.0;
self.itemLayoutAttributes = [[NSMutableArray alloc] init];
self.headerLayoutAttributes = [[NSMutableArray alloc] init];
self.footerLayoutAttributes = [[NSMutableArray alloc] init];
self.heightOfSections = [[NSMutableArray alloc] init];
self.shouldanimationArr = [[NSMutableArray alloc] init];
}
3、重写prepareLayout方法,在重写此方法之前,我们需要对属性数组和变量进行清空布局属性。
- (void)prepareLayout {
[super prepareLayout];
/*断言判断dataSource是否实现*/
NSAssert(self.dataSource != nil, @"CommonLayout.dat