最近在開發(fā)軟件的時(shí)候被產(chǎn)品經(jīng)理要求,要讓UICollectionView上面的cell之間的距離要被固定,但是cell得寬度不一定,所以一行有幾個(gè)cell其實(shí)不固定,所以其實(shí)cell之間的間距不一定,cell之間最終距離不是你設(shè)置的,而是由系統(tǒng)把一行中cell寬度減去,剩下的空白格平均分配的.所以我一開始寫出來的效果看起來不是很規(guī)則
所以嘍,產(chǎn)品經(jīng)理不同意這樣,說看起來不是很規(guī)則锯茄,然后只能去網(wǎng)上找,做種找到了別人的一些例子窿给,最終弄出來一個(gè)貌似還能看的規(guī)則。
最近需求還沒下來单起,所以把很久之前的這個(gè)代碼給重新折騰了一下抱怔,支持靠左睹酌,居中伞租,靠右楼眷,等間距對(duì)齊之景。整體邏輯也比之前清晰了一些斤富。
#import <UIKit/UIKit.h>
typedef NS_ENUM(NSInteger,AlignType){
AlignWithLeft,
AlignWithCenter,
AlignWithRight
};
@interface JYEqualCellSpaceFlowLayout : UICollectionViewFlowLayout
//兩個(gè)Cell之間的距離
@property (nonatomic,assign)CGFloat betweenOfCell;
//cell對(duì)齊方式
@property (nonatomic,assign)AlignType cellType;
-(instancetype)initWthType : (AlignType)cellType;
//全能初始化方法 其他方式初始化最終都會(huì)?走到這里
-(instancetype)initWithType:(AlignType) cellType betweenOfCell:(CGFloat)betweenOfCell;
@end
#import "JYEqualCellSpaceFlowLayout.h"
@interface JYEqualCellSpaceFlowLayout(){
//在居中對(duì)齊的時(shí)候需要知道這行所有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];
//用來臨時(shí)存放一行的Cell數(shù)組
NSMutableArray * layoutAttributesTemp = [[NSMutableArray alloc]init];
for (NSUInteger index = 0; index < layoutAttributes.count ; index++) {
UICollectionViewLayoutAttributes *currentAttr = layoutAttributes[index]; // 當(dāng)前cell的位置信息
UICollectionViewLayoutAttributes *previousAttr = index == 0 ? nil : layoutAttributes[index-1]; // 上一個(gè)cell 的位置信
UICollectionViewLayoutAttributes *nextAttr = index + 1 == layoutAttributes.count ?
nil : layoutAttributes[index+1];//下一個(gè)cell 位置信息
//加入臨時(shí)數(shù)組
[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);
//如果當(dāng)前cell是單獨(dú)一行
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];
}
}
//如果下一個(gè)cell在本行,這開始調(diào)整Frame位置
else if( currentY != nextY) {
[self setCellFrameWith:layoutAttributesTemp];
}
}
return layoutAttributes;
}
//調(diào)整屬于同一行的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 {
//兩個(gè)Cell之間的距離
var betweenOfCell : CGFloat{
didSet{
self.minimumInteritemSpacing = betweenOfCell
}
}
//cell對(duì)齊方式
var cellType : AlignType = AlignType.center
//在居中對(duì)齊的時(shí)候需要知道這行所有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
}
/// 調(diào)整Cell的Frame
///
/// - Parameter layoutAttributes: layoutAttribute 數(shù)組
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在這里