I'm trying to make UICollectionView work like UITableView (I want the extra flexibility of collection view instead of just going with table view, both for some current and possible future feature extensions); having a fixed width (screen width) and dynamic cell height (just like iOS 8's new table view feature). I've been struggling a lot to get it working. First, I've enabled automatic sizing by setting an estimated size on layout on my collection view subclass:
UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout*)self.collectionViewLayout;
layout.estimatedItemSize = CGSizeMake(SCREEN_WIDTH, 100);
Then I've set up my constraints of my custom cell in Interface Builder to let it grow according to my text view's content.
I've also set up a width constraint equal to screen width programatically, otherwise my cells were having a default width of 50pt. Inside my custom cell's awakeFromNib
:
[self addConstraint: [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:SCREEN_WIDTH]];
It seems to work for width. When I run my app, it breaks height constraints as my own constraints conflict with UIView-Encapsulated-Layout-Height
which is set to 100 (this actually means that auto-height is not really working well).
I lower the priority from my vertical constraints, especially the one with textview (which grows depending on its content) from required (1000) to some lower number (900). I'm not getting broken constraints anymore, but that's because we don't need to break constraints anymore as UIView-Encapsulated-Layout-Height
takes precedence. Result is exactly the same. Here is what I'm getting:
There is no problem with the GIF above. It really does jump at one point exactly as seen on the GIF.
How can I prevent this behavior and make my collection view cells grow in height dynamically (of course, without creating a dummy offscreen cell to calculate view sizes)?
I don't need to support iOS 7, so iOS 8-and-above-only solutions are welcome.
UPDATE: If I implement preferredLayoutAttributesFittingAttributes:
method as seen on the answer to UICollectionView Self Sizing Cells with Auto Layout:
-(UICollectionViewLayoutAttributes *)preferredLayoutAttributesFittingAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes{
UICollectionViewLayoutAttributes *attrs = [layoutAttributes copy];
CGRect frame = attrs.frame;
self.frame = frame;
[self setNeedsLayout];
[self layoutIfNeeded];
float desiredHeight = [self.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
frame.size.height = desiredHeight;
attrs.frame = frame;
return attrs;
}
Then it's always returning the NIB's original view size that was in the Interface Builder even though I've set:
self.translatesAutoresizingMaskIntoConstraints = NO;
self.contentView.translatesAutoresizingMaskIntoConstraints = NO;
I have no idea why it's returning an incorrect value.
After spending hours and days, I've decided to go back to table view. While collection view offers great flexibility and is definitely the future, it's just not there yet.