UICollectionView的自定义布局

来源:互联网 发布:java copy文件 编辑:程序博客网 时间:2024/05/21 14:04

UICollectionView控件的使用一般会在特殊的界面处理上,但是也有比较规矩的应用软件会用UICollectionView。例如效果如下的界面;
这里写图片描述
下面开始讲述我的界面是如何做的。

1.首先我会把界面分成5个section,这就需要上篇文章讲述的自定义UICollectionReusableView 和自定义自定义UICollectioncell相结合了。

2.每个section下的cell需要不同的布局样式,这个跟以前的uitableview的自定义cell是一毛一样的。

3.UICollectionViewFlowLayout对布局的定义(最重要的也是这个)

下面上代码:

//自定义的五个section-(UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath{    UICollectionReusableView *resuableView;    //每一个section的headerview    if (indexPath.section == 0) {        if (kind == UICollectionElementKindSectionHeader) {            UICollectionReusableView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"cycleHeader" forIndexPath:indexPath];            headerView.backgroundColor = QFWhiteColor;            [headerView addSubview:self.sdcycleScroll];            self.sdcycleScroll.sd_layout.spaceToSuperView(UIEdgeInsetsMake(0, 0, 0, 0));            resuableView = headerView;        }        else        {            return nil;        }    }    else    {        UICollectionReusableView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"headerView" forIndexPath:indexPath];        headerView.backgroundColor = QFWhiteColor;        //清空子view        [QFCommon removeAllSubViewsOnView:headerView];        if (indexPath.section == 1)        {            resuableView = headerView;        }        else        {            _mainModel = _mainList[indexPath.section];            //标题            UILabel *titleLable = [UILabel new];            titleLable.backgroundColor = QFClearColor;            titleLable.textColor = QFSectionTitleColor;            titleLable.font = QFUsualBody;            titleLable.textAlignment = NSTextAlignmentCenter;            titleLable.text = _mainModel.section.secction_chinses;            [headerView addSubview:titleLable];            //分割线            UILabel *sectionLine = [UILabel new];            sectionLine.backgroundColor = QFLineColor;            [headerView addSubview:sectionLine];            //英文            UILabel *englishLable = [UILabel new];            englishLable.backgroundColor = QFClearColor;            englishLable.textColor = QFSectionSubTitleColor;            englishLable.font = QFUsualLabel;            englishLable.textAlignment = NSTextAlignmentCenter;            englishLable.text = _mainModel.section.section_english;            [headerView addSubview:englishLable];            //布局约束            titleLable.sd_layout.leftSpaceToView(headerView,0).topSpaceToView(headerView,5).rightSpaceToView(headerView,0).heightIs(25);            sectionLine.sd_layout.topSpaceToView(titleLable,0).centerXEqualToView(headerView).widthIs(50).heightIs(1);            englishLable.sd_layout.leftSpaceToView(headerView,0).topSpaceToView(sectionLine,0).rightSpaceToView(headerView,0).heightIs(20);            resuableView = headerView;        }    }    return resuableView;}

2.不同的cell

两组cell

//每行3个方格的cell

每行3个方格的cell

//下面的多种cell

不同样式的cell

最后将自定义的layout代码上一下,这个也是最重要的。

#import "ForeverGuardFlowLayout.h"//默认的边缘间距static const UIEdgeInsets QFDefaultEdgeInsets = {10,10,10,10};@interface ForeverGuardFlowLayout()/** 存放所有cell的布局属性 */@property (nonatomic, strong) NSMutableArray *attrsArray;/** 存放所有列的当前高度 */@property (nonatomic, strong) NSMutableArray *columnHeights;/** 内容的高度 */@property (nonatomic, assign) CGFloat contentHeight;//布局进行到的section@property (nonatomic, assign) NSInteger lastSection;//布局到目前为止的长度@property (nonatomic, assign) CGFloat loadHeight;@end@implementation ForeverGuardFlowLayout#pragma mark-懒加载-(NSMutableArray *)columnHeights{    if (!_columnHeights) {        _columnHeights = [NSMutableArray array];    }    return _columnHeights;}- (NSMutableArray *)attrsArray{    if (!_attrsArray) {        _attrsArray = [NSMutableArray array];    }    return _attrsArray;}#pragma mark -默认方法/** * 决定cell的排布 */- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect{    return self.attrsArray;}-(CGSize)collectionViewContentSize{    return CGSizeMake(0, self.contentHeight + _wholeEdgeInsets.bottom);}#pragma mark-设置边框、间距这些常量//全局边距的设定(不设定就按照默认值为(10,10,10,10)计算)-(void)setWholeEdgeInsets:(UIEdgeInsets)wholeEdgeInsets{    if (wholeEdgeInsets.left != QFDefaultEdgeInsets.left || wholeEdgeInsets.right != QFDefaultEdgeInsets.right || wholeEdgeInsets.top != QFDefaultEdgeInsets.top || wholeEdgeInsets.bottom != QFDefaultEdgeInsets.bottom ) {        _wholeEdgeInsets = wholeEdgeInsets;    }    else    {        _wholeEdgeInsets = QFDefaultEdgeInsets;    }}#pragma mark-关键的两个方法-(void)prepareLayout{    [super prepareLayout];    //防止_lastSection=0时无法对section=0布局,才对_lastSectiobn设置一个非0的数值    _lastSection = 10000;    //初始化常量    self.contentHeight = 0.0;    //清除以前计算的所有高度    [self.columnHeights removeAllObjects];    //获取第一行有几列    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];    NSInteger firstColumnCount = [self.delegate foreverGuardFlowLayoutColumnCountWithIndexpath:indexPath];    //给第一行的高度做初始化    for (NSInteger i=0; i<firstColumnCount; i++) {        [self.columnHeights addObject:@(_wholeEdgeInsets.top)];    }    //清除所有的布局属性    [self.attrsArray removeAllObjects];    //开始创建每一个Cell的布局属性    NSInteger sectionNum = [self.collectionView numberOfSections];    for (NSInteger m = 0; m<sectionNum; m++) {        NSInteger rowNum = [self.collectionView numberOfItemsInSection:m];        for (NSInteger n = 0; n<rowNum; n++) {            //创建对应的Indexpath            NSIndexPath *indexPath = [NSIndexPath indexPathForRow:n inSection:m];            // 获取indexPath位置cell对应的布局属性            UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:indexPath];            [self.attrsArray addObject:attrs];        }    }}-(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{    // 创建布局属性    UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];    //声明cell的位置和大小    CGFloat cellWidth,cellHeighth,cellX,cellY;    //初始化必要的变量    NSInteger destColumn = 0;    //先取出第一列的高度作为比较的初始值    CGFloat minColumnHeight = [self.columnHeights[0]floatValue];    /*******根据自定义协议回调方法取出在外声明的cell的相关数据********/    CGSize cellSize = [self.delegate foreverGuardFlowLayoutCellSizeWithIndexpath:indexPath];    CGFloat sectionHeight = [self.delegate foreverGuardFlowLayoutSectionHeightWithIndexpath:indexPath];    NSInteger sectionColumn = [self.delegate foreverGuardFlowLayoutColumnCountWithIndexpath:indexPath];    CGFloat columnMargin = [self.delegate foreverGuardFlowLayoutColumnMarginWithIndexpath:indexPath];    CGFloat rowMargin = [self.delegate foreverGuardFlowLayoutRowMarginWithIndexpath:indexPath];    //当前的section和row的数值    NSInteger currentSection = indexPath.section;    NSInteger currentRow = indexPath.row;    cellWidth = cellSize.width;    cellHeighth = cellSize.height;    //对cell开始布局    if (_lastSection == currentSection) {        //排放的位置(放到第几列)        destColumn = currentRow % sectionColumn;        //获取cell的X值        cellX = self.wholeEdgeInsets.left + destColumn * (cellWidth + columnMargin);        //获取cell的Y值        for (NSInteger i = 1; i < sectionColumn; i++) {            // 取得第i列的高度            CGFloat columnHeight = [self.columnHeights[i] doubleValue];            if (minColumnHeight > columnHeight) {                minColumnHeight = columnHeight;            }        }        cellY = minColumnHeight;        if (cellY != self.wholeEdgeInsets.top)            cellY += rowMargin;        if (currentRow < sectionColumn) {            cellY = _loadHeight;        }        attrs.frame = CGRectMake(cellX, cellY, cellWidth, cellHeighth);    }    else    {        //添加一个section然后再添加section下的第一个cell        _lastSection = currentSection;        cellX = self.wholeEdgeInsets.left;        for (NSInteger i = 1; i < sectionColumn; i++) {            // 取得第i列的高度            CGFloat columnHeight = [self.columnHeights[i] doubleValue];            if (minColumnHeight < columnHeight) {                minColumnHeight = columnHeight;            }        }        cellY = minColumnHeight;        cellY += rowMargin;        //添加section的header部分到布局属性数组里面        UICollectionViewLayoutAttributes *layoutAttributesHeader = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader withIndexPath:indexPath];        layoutAttributesHeader.frame = CGRectMake(0, cellY, QFDEVICE_WIDTH, sectionHeight);        [self.attrsArray addObject:layoutAttributesHeader];        _loadHeight = cellY +sectionHeight;        attrs.frame = CGRectMake(cellX, _loadHeight, cellWidth, cellHeighth);    }    // 更新最短那列的高度    self.columnHeights[destColumn] = @(CGRectGetMaxY(attrs.frame));    // 记录内容的高度    CGFloat columnHeight = [self.columnHeights[destColumn] floatValue];    if (self.contentHeight < columnHeight) {        self.contentHeight = columnHeight;    }    return attrs;}
原创粉丝点击