5

I want to layout cells from left to right.So I use UICollectionViewFlowLayout:

UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
// use this for let cell width fit for label width
layout.estimatedItemSize = CGSizeMake(80, 30);
self.collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout];

The cell's width is fit for the label's width:

// cell code
@implementation CQGoodsSearchCell

- (void)setupUI {
    self.contentView.layer.cornerRadius = 15;
    self.contentView.layer.masksToBounds = YES;
    self.contentView.backgroundColor = [UIColor colorWithRed:1.00 green:1.00 blue:1.00 alpha:1.00];

    self.nameLabel = [[UILabel alloc] init];
    [self.contentView addSubview:self.nameLabel];
    self.nameLabel.font = [UIFont systemFontOfSize:15];
    self.nameLabel.textColor = [UIColor colorWithRed:0.18 green:0.18 blue:0.18 alpha:1.00];
    [self.nameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.height.mas_equalTo(30);
        make.top.bottom.mas_offset(0);
        make.left.mas_offset(10);
        make.right.mas_offset(-10);
    }];
}

Everything gose well when there is more than one cell:

Two cells aligned to the left

However,the cell is in the center when there is only one cell:

One cell in the center

If I use itemSize instead of estimatedItemSize, it is OK:

layout.itemSize = CGSizeMake(80, 30);

Once cell aligned to the left

I am really confused about this. Having the cell in the center of the collection view is not what I want but I also want to use Auto Layout so the cell's width adjusts itself.

So is there any way to avoid this?

puzzle
  • 6,071
  • 1
  • 25
  • 30
无夜之星辰
  • 5,426
  • 4
  • 25
  • 48

3 Answers3

9

Select none in the Estimate Size option. If the collection view has only one item, it will be left-aligned instead of being in the center.

enter image description here

Mimi
  • 169
  • 2
  • 2
3

Basically this is the same issue I discuss here:

https://stackoverflow.com/a/52428617/341994

In sum, the feature you are trying to use, self-sizing collection view cells, doesn't work and has never worked. That is why, as you correctly say,

If I use itemSize instead of estimatedItemSize, it will be OK

That's right! It isn't your bug; it's an iOS bug. Self-sizing collection view cells do not work. Either the app crashes or the flow layout is incorrect.

So that's the solution. Do not use estimatedItemSize. Instead, calculate the correct size yourself and provide it in your implementation of

func collectionView(_ collectionView: UICollectionView, 
    layout collectionViewLayout: UICollectionViewLayout, 
    sizeForItemAt indexPath: IndexPath) -> CGSize {
        // calculate/obtain correct size and return it
}
matt
  • 515,959
  • 87
  • 875
  • 1,141
2

Also,use custom UICollectionViewLayout can solve this problem:

For Objective-C:

@interface CQLeftSideLayout : UICollectionViewFlowLayout

@end

@implementation CQLeftSideLayout

- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {

    NSArray *attributes = [super layoutAttributesForElementsInRect:rect];

    if (attributes.count == 1) {
        UICollectionViewLayoutAttributes *currentAttributes = attributes.firstObject;
        currentAttributes.frame = CGRectMake(self.sectionInset.left, currentAttributes.frame.origin.y, currentAttributes.frame.size.width, currentAttributes.frame.size.height);
    }

    return attributes;

}

@end

For Swift:

class LeftSideLayout: UICollectionViewFlowLayout {

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

        let attributes = super.layoutAttributesForElements(in: rect)

        if attributes?.count == 1 {

            if let currentAttribute = attributes?.first {
                currentAttribute.frame = CGRect(x: self.sectionInset.left, y: currentAttribute.frame.origin.y, width: currentAttribute.frame.size.width, height: currentAttribute.frame.size.height)
            }

        }


        return attributes

    }

}
无夜之星辰
  • 5,426
  • 4
  • 25
  • 48