UICollectionView中Cell左对齐 居中 右对齐 等间距

https://www.jianshu.com/p/ac3edf92c5fd

2016.06.14 16:22* 字数 273 阅读 14983评论 74喜欢 69

最近在开发软件的时候被产品经理要求,要让UICollectionView上面的cell之间的距离要被固定,但是cell得宽度不一定,所以一行有几个cell其实不固定,所以其实cell之间的间距不一定,cell之间最终距离不是你设置的,而是由系统把一行中cell宽度减去,剩下的空白格平均分配的.所以我一开始写出来的效果看起来不是很规则

 

 

 

屏幕快照

 

所以喽,产品经理不同意这样,说看起来不是很规则,然后只能去网上找,做种找到了别人的一些例子,最终弄出来一个貌似还能看的规则。

 

 


屏幕快照

最近需求还没下来,所以把很久之前的这个代码给重新折腾了一下,支持靠左,居中,靠右,等间距对齐。整体逻辑也比之前清晰了一些。

 


靠左等间距.png

 


居中等间距.png

 


靠右等间距.png

#import <UIKit/UIKit.h>

typedef NS_ENUM(NSInteger,AlignType){

    AlignWithLeft,

    AlignWithCenter,

    AlignWithRight

};

@interface JYEqualCellSpaceFlowLayout : UICollectionViewFlowLayout

//两个Cell之间的距离

@property (nonatomic,assign)CGFloat betweenOfCell;

//cell对齐方式

@property (nonatomic,assign)AlignType cellType;

 

-(instancetype)initWthType : (AlignType)cellType;

//全能初始化方法 其他方式初始化最终都会走到这里

-(instancetype)initWithType:(AlignType) cellType betweenOfCell:(CGFloat)betweenOfCell;

 

@end

#import "JYEqualCellSpaceFlowLayout.h"

@interface JYEqualCellSpaceFlowLayout(){

    //在居中对齐的时候需要知道这行所有cell的宽度总和

    CGFloat _sumCellWidth ;

}

@end

 

@implementation JYEqualCellSpaceFlowLayout

-(instancetype)init{

    return [self initWithType:AlignWithCenter betweenOfCell:5.0];

}

-(void)setBetweenOfCell:(CGFloat)betweenOfCell{

    _betweenOfCell = betweenOfCell;

    self.minimumInteritemSpacing = betweenOfCell;

}

-(instancetype)initWthType:(AlignType)cellType{

    return [self initWithType:cellType betweenOfCell:5.0];

}

-(instancetype)initWithType:(AlignType)cellType betweenOfCell:(CGFloat)betweenOfCell{

    self = [super init];

    if (self){

        self.scrollDirection = UICollectionViewScrollDirectionVertical;

        self.minimumLineSpacing = 5;

        self.minimumInteritemSpacing = 5;

        self.sectionInset = UIEdgeInsetsMake(5, 5, 5, 5);

        _betweenOfCell = betweenOfCell;

        _cellType = cellType;

    }

    return self;

}

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {

    NSArray * layoutAttributes_t = [super layoutAttributesForElementsInRect:rect];

    NSArray * layoutAttributes = [[NSArray alloc]initWithArray:layoutAttributes_t copyItems:YES];

    //用来临时存放一行的Cell数组

    NSMutableArray * layoutAttributesTemp = [[NSMutableArray alloc]init];

    for (NSUInteger index = 0; index < layoutAttributes.count ; index++) {

        

        UICollectionViewLayoutAttributes *currentAttr = layoutAttributes[index]; // 当前cell的位置信息

        UICollectionViewLayoutAttributes *previousAttr = index == 0 ? nil : layoutAttributes[index-1]; // 上一个cell 的位置信

        UICollectionViewLayoutAttributes *nextAttr = index + 1 == layoutAttributes.count ?

        nil : layoutAttributes[index+1];//下一个cell 位置信息

        

        //加入临时数组

        [layoutAttributesTemp addObject:currentAttr];

        _sumCellWidth += currentAttr.frame.size.width;

        

        CGFloat previousY = previousAttr == nil ? 0 : CGRectGetMaxY(previousAttr.frame);

        CGFloat currentY = CGRectGetMaxY(currentAttr.frame);

        CGFloat nextY = nextAttr == nil ? 0 : CGRectGetMaxY(nextAttr.frame);

        //如果当前cell是单独一行

        if (currentY != previousY && currentY != nextY){

            if ([currentAttr.representedElementKind isEqualToString:UICollectionElementKindSectionHeader]) {

                [layoutAttributesTemp removeAllObjects];

                _sumCellWidth = 0.0;

            }else if ([currentAttr.representedElementKind isEqualToString:UICollectionElementKindSectionFooter]){

                [layoutAttributesTemp removeAllObjects];

                _sumCellWidth = 0.0;

            }else{

                [self setCellFrameWith:layoutAttributesTemp];

            }

        }

        //如果下一个cell在本行,这开始调整Frame位置

        else if( currentY != nextY) {

            [self setCellFrameWith:layoutAttributesTemp];

        }

    }

    return layoutAttributes;

}

//调整属于同一行的cell的位置frame

-(void)setCellFrameWith:(NSMutableArray*)layoutAttributes{

    CGFloat nowWidth = 0.0;

    switch (_cellType) {

        case AlignWithLeft:

            nowWidth = self.sectionInset.left;

            for (UICollectionViewLayoutAttributes * attributes in layoutAttributes) {

                CGRect nowFrame = attributes.frame;

                nowFrame.origin.x = nowWidth;

                attributes.frame = nowFrame;

                nowWidth += nowFrame.size.width + self.betweenOfCell;

            }

            _sumCellWidth = 0.0;

            [layoutAttributes removeAllObjects];

            break;

            

        case AlignWithCenter:

            nowWidth = (self.collectionView.frame.size.width - _sumCellWidth - ((layoutAttributes.count - 1) * _betweenOfCell)) / 2;

            for (UICollectionViewLayoutAttributes * attributes in layoutAttributes) {

                CGRect nowFrame = attributes.frame;

                nowFrame.origin.x = nowWidth;

                attributes.frame = nowFrame;

                nowWidth += nowFrame.size.width + self.betweenOfCell;

            }

            _sumCellWidth = 0.0;

            [layoutAttributes removeAllObjects];

            break;

            

        case AlignWithRight:

            nowWidth = self.collectionView.frame.size.width - self.sectionInset.right;

            for (NSInteger index = layoutAttributes.count - 1 ; index >= 0 ; index-- ) {

                UICollectionViewLayoutAttributes * attributes = layoutAttributes[index];

                CGRect nowFrame = attributes.frame;

                nowFrame.origin.x = nowWidth - nowFrame.size.width;

                attributes.frame = nowFrame;

                nowWidth = nowWidth - nowFrame.size.width - _betweenOfCell;

            }

            _sumCellWidth = 0.0;

            [layoutAttributes removeAllObjects];

            break;

    }

}

 

@end

OC版本的Demo在这里

------------------------------------------------------分界线-----------------------------------------------------

下面是Swift版本的代码

import UIKit

enum AlignType : NSInteger {

    case left = 0

    case center = 1

    case right = 2

}

class JYEqualCellSpaceFlowLayout: UICollectionViewFlowLayout {

    //两个Cell之间的距离

    var betweenOfCell : CGFloat{

        didSet{

            self.minimumInteritemSpacing = betweenOfCell

        }

    }

    //cell对齐方式

    var cellType : AlignType = AlignType.center

    //在居中对齐的时候需要知道这行所有cell的宽度总和

    var sumCellWidth : CGFloat = 0.0

    

    override init() {

        betweenOfCell = 5.0

        super.init()

        scrollDirection = UICollectionViewScrollDirection.vertical

        minimumLineSpacing = 5

        sectionInset = UIEdgeInsetsMake(5, 5, 5, 5)

    }

    convenience init(_ cellType:AlignType){

        self.init()

        self.cellType = cellType

    }

    convenience init(_ cellType: AlignType, _ betweenOfCell: CGFloat){

        self.init()

        self.cellType = cellType

        self.betweenOfCell = betweenOfCell

    }

    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {

        

        let layoutAttributes_super : [UICollectionViewLayoutAttributes] = super.layoutAttributesForElements(in: rect) ?? [UICollectionViewLayoutAttributes]()

        let layoutAttributes:[UICollectionViewLayoutAttributes] = NSArray(array: layoutAttributes_super, copyItems:true)as! [UICollectionViewLayoutAttributes]

        var layoutAttributes_t : [UICollectionViewLayoutAttributes] = [UICollectionViewLayoutAttributes]()

        for index in 0..<layoutAttributes.count{

            

            let currentAttr = layoutAttributes[index]

            let previousAttr = index == 0 ? nil : layoutAttributes[index-1]

            let nextAttr = index + 1 == layoutAttributes.count ?

                nil : layoutAttributes[index+1]

            

            layoutAttributes_t.append(currentAttr)

            sumCellWidth += currentAttr.frame.size.width

            

            let previousY :CGFloat = previousAttr == nil ? 0 : previousAttr!.frame.maxY

            let currentY :CGFloat = currentAttr.frame.maxY

            let nextY:CGFloat = nextAttr == nil ? 0 : nextAttr!.frame.maxY

            

            if currentY != previousY && currentY != nextY{

                if currentAttr.representedElementKind == UICollectionElementKindSectionHeader{

                    layoutAttributes_t.removeAll()

                    sumCellWidth = 0.0

                }else if currentAttr.representedElementKind == UICollectionElementKindSectionFooter{

                    layoutAttributes_t.removeAll()

                    sumCellWidth = 0.0

                }else{

                    self.setCellFrame(with: layoutAttributes_t)

                    layoutAttributes_t.removeAll()

                    sumCellWidth = 0.0

                }

            }else if currentY != nextY{

                self.setCellFrame(with: layoutAttributes_t)

                layoutAttributes_t.removeAll()

                sumCellWidth = 0.0

            }

        }

        return layoutAttributes

    }

    

    /// 调整Cell的Frame

    ///

    /// - Parameter layoutAttributes: layoutAttribute 数组

    func setCellFrame(with layoutAttributes : [UICollectionViewLayoutAttributes]){

        var nowWidth : CGFloat = 0.0

        switch cellType {

        case AlignType.left:

            nowWidth = self.sectionInset.left

            for attributes in layoutAttributes{

                var nowFrame = attributes.frame

                nowFrame.origin.x = nowWidth

                attributes.frame = nowFrame

                nowWidth += nowFrame.size.width + self.betweenOfCell

            }

            break;

        case AlignType.center:

            nowWidth = (self.collectionView!.frame.size.width - sumCellWidth - (CGFloat(layoutAttributes.count - 1) * betweenOfCell)) / 2

            for attributes in layoutAttributes{

                var nowFrame = attributes.frame

                nowFrame.origin.x = nowWidth

                attributes.frame = nowFrame

                nowWidth += nowFrame.size.width + self.betweenOfCell

            }

            break;

        case AlignType.right:

            nowWidth = self.collectionView!.frame.size.width - self.sectionInset.right

            for var index in 0 ..< layoutAttributes.count{

                index = layoutAttributes.count - 1 - index

                let attributes = layoutAttributes[index]

                var nowFrame = attributes.frame

                nowFrame.origin.x = nowWidth - nowFrame.size.width

                attributes.frame = nowFrame

                nowWidth = nowWidth - nowFrame.size.width - betweenOfCell

            }

            break;

        }

    }

    

    required init?(coder aDecoder: NSCoder) {

        fatalError("init(coder:) has not been implemented")

    }

}

Swift版本Demo在这里

OC版本的Demo在这里

 

posted @ 2019-03-28 20:53  sundaysios  阅读(2103)  评论(0)    收藏  举报