美文网首页
UICollectionViewLayout高度自定义瀑布流

UICollectionViewLayout高度自定义瀑布流

作者: 八匹马_BPM | 来源:发表于2020-03-07 11:52 被阅读0次

知识重在分享, 只有分享才能逐步提高创新力!

实现简单的UICollectionView必须实现UICollectionViewDataSource协议, 知道几组, 每组几个item, 和UITableView不同的是UICollectionView每个item的具体布局信息需要UICollectionViewFlowLayout类来提供, 如果没有实现UICollectionViewDelegateFlowLayout协议, 那么每个item的布局约束可以直接使用

@property (nonatomic) CGFloat minimumLineSpacing; //行间距

@property (nonatomic) CGFloat minimumInteritemSpacing; //item间距

@property (nonatomic) CGSize itemSize; //item大小

@property (nonatomic) CGSize headerReferenceSize; //组头大小

@property (nonatomic) CGSize footerReferenceSize; //组尾大小

@property (nonatomic) UIEdgeInsets sectionInset; //内容内间距

这些属性来设置

如果遵守了UICollectionViewDelegateFlowLayout协议, 那么每个item的布局约束需要实现代理方法来设置, 具体如下:

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath; //每个item大小

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section; //内容内间距

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section; //行间距

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section; //item间距

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section; //组头大小

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section; //组尾大小

对于遵守UICollectionViewDelegateFlowLayout协议的UICollectionView, 比如设置

UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc]init];

    flowLayout.minimumLineSpacing = 10;

    flowLayout.minimumInteritemSpacing = 10;

    flowLayout.sectionInset = UIEdgeInsetsMake(20, 20, 20, 20);

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{

    CGFloat width = self.view.bounds.size.width;

    return CGSizeMake((width-40-20)/3, rand()%40+50);

}

那么效果会是这样的:

垂直排版系统以最高的item为基准, 布局同一行的其他item

这样的效果有时候并不能满足我们的业务需求, 我们的业务有时候是需要垂直布局, 可以设置几列, 每列之间的item等间距布局, 这时候系统默认的行为已经不能满足我们的需要

下面看看如何解决这种业务需求的布局要求:

对于UICollectionView的item的不规则布局以及带动画布局, 都需要自定义UICollectionViewLayout这个类是专门来设置UICollectionView子视图布局的类,其中比较常用的方法有以下几个:

- (void)prepareLayout; //每次UICollectionView添加到父视图的时候, 都会加载该方法, 该方法只会调用一次, 为此可以在该方法中, 初始化一些需要的信息

- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect; //返回给定矩形中所有视图的数组布局属性实例

- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath; //每个item的布局属性在此方法中设计

- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath; //每个组头组尾的布局属性在此方法中设计

- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString*)elementKind atIndexPath:(NSIndexPath *)indexPath; //设计UICollectionView背景视图的布局属性在此方法中进行

UICollectionViewLayoutAttributes是很重要的一个类, 它封装了UICollectionView的cell, 组头组尾, DecorationView(背景视图)的布局属性, 包含属性列表如下:

@property (nonatomic) CGRect frame; //UICollectionView每个子视图的位置,大小

@property (nonatomic) CGPoint center; // UICollectionView每个子视图在父视图的中心点坐标

@property (nonatomic) CGSize size; //UICollectionView每个子视图的大小

@property (nonatomic) CATransform3D transform3D; //可以使用该属性, 设置每个子视图的3D动画效果

@property (nonatomic) CGRect bounds API_AVAILABLE(ios(7.0)); 

@property (nonatomic) CGAffineTransform transform API_AVAILABLE(ios(7.0)); 

@property (nonatomic) CGFloat alpha;

@property (nonatomic) NSInteger zIndex; // default is 0 用于3D动画开发上面, 表示空间的深度

@property (nonatomic, getter=isHidden) BOOL hidden; // As an optimization, UICollectionView might not create a view for items whose hidden attribute is YES

@property (nonatomic, strong) NSIndexPath *indexPath; //每个子视图所在的组和几个item的标示

为此为了满足产品的需求, 我们可以自定义一个了继承UICollectionViewLayout, 然后给自定义类添加几个协议方法和属性, 例如:

@protocol WaterfallFlowLayoutDelegate <NSObject>

@required

//根据每个item的宽计算高

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(WaterfallFlowLayout*)collectionViewLayout heightForWidth:(CGFloat)width atIndexPath:(NSIndexPath*)indexPath;

@optional

//当然你也可以加上几个代理方法表示行间距, item间距, 内容内间距等, 这样也可以灵活设置UICollectionViewFlowLayout的每个布局属性

//设置组头的大小

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(WaterfallFlowLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section;

//设置组尾的大小

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(WaterfallFlowLayout*)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section;

@end

@interface WaterfallFlowLayout : UICollectionViewLayout

@property(nonatomic,assign)UIEdgeInsets sectionInset; //sectionInset

@property(nonatomic,assign)CGFloat lineSpacing;  //line space

@property(nonatomic,assign)CGFloat itemSpacing; //item space

@property(nonatomic,assign)CGFloat colCount; //column count

@property(nonatomic,weak)id<WaterfallFlowLayoutDelegate> delegate;

@end

最后就可以在- (void)prepareLayout;方法中初始化一些布局时候需要用到的信息

在- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;方法中设置每个item的UICollectionViewLayoutAttributes信息

在- (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath;方法中设置组头组尾的UICollectionViewLayoutAttributes信息

在- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect;方法中返回所有计算好的包含每个子视图的UICollectionViewLayoutAttributes的数组

在- (CGSize)collectionViewContentSize;方法中根据最大列的高度, 设置可滚动区域的大小

最终实现效果如下:

带组头组尾, 可设置内容内边距, item间距和行间距

具体代码如下, 不容易理解的地方已经加上了详细的解释:  

GitHub: VerticalEqualWidthDemo

相关文章

网友评论

      本文标题:UICollectionViewLayout高度自定义瀑布流

      本文链接:https://www.haomeiwen.com/subject/wbgfdhtx.html