Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UICollectionViewFlowLayout's estimatedItemSize breaks scrolling?

(EDIT : it seems to be working fine starting with iOS 9. I did not make extensive tests, but the example works. This confirms the bug present in iOS 8.)

I spent a lot of time testing UICollectionView's Flow Layout self sizing behavior. After a lot of frustration the issue is narrowed down to the fact that as soon as one sets the estimatedItemSize to a non-zero size, the scrolling no longer works properly.

In my example instead of showing 40 items it only displays 32.

I've copy pasted the code bellow. I've tested many things starting with a Swift version.

Basically it fails to calculate and/or properly update the layout's collectionViewContentSize()

Here is a complete demo http://git.io/AIrHNA

Anybody can point me in the right direction?

Thank you

@implementation ViewControllerObjcC

static NSString * const reuseIdentifier = @"Cell";
-(UICollectionViewFlowLayout*)flowLayout{
  return (UICollectionViewFlowLayout*)self.collectionViewLayout;
}

- (void)viewDidLoad {
  [super viewDidLoad];
  [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:reuseIdentifier];
  CGSize estimatedSize = CGSizeMake(self.view.frame.size.width, 25.0);
  BOOL testEstimatedItemSize = true;
  if (testEstimatedItemSize) {
    [self flowLayout].estimatedItemSize = estimatedSize;
  }else{
    [self flowLayout].itemSize = estimatedSize;
  }

}

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
    return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return 40;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
  UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
  UILabel* label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 40, 30)];
  [cell.contentView addSubview:label];
  label.text = [NSString stringWithFormat:@"%ld",(long)indexPath.row];
  label.backgroundColor = [UIColor redColor];
  return cell;
}
like image 267
Adrian Avatar asked Dec 26 '14 17:12

Adrian


1 Answers

From Apple's Document,

Specifically, cells that are not onscreen are assumed to be the estimated height.

This is my guess.

When the estimated height is smaller than the actual cell height, the collection view's content size prediction is smaller than the actual content size.

Therefore it display only displays 32 of the total 40 cells.

In my project, all celsl are shown when a large estimated size is used.

like image 82
Dennis Li Avatar answered Oct 18 '22 18:10

Dennis Li