I've been toying with dynamic UICollectionViewCell's and have noticed that on iOS 8 calling cell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
on a UICollectionViewCell
returns an incorrect width. Currently the only workaround that addresses this is to explicitly add a width constraint to force the cell's width. The below code is used in a Cell subclass:
func calculatePreferredHeightForFrame(frame: CGRect) -> CGFloat {
var newFrame = frame
self.frame = newFrame
let widthConstraint = NSLayoutConstraint(item: contentView, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: CGRectGetWidth(frame))
contentView.addConstraint(widthConstraint)
self.setNeedsUpdateConstraints()
self.updateConstraintsIfNeeded()
self.setNeedsLayout()
self.layoutIfNeeded()
let desiredHeight: CGFloat = self.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
newFrame.size.height = CGFloat(ceilf(Float(desiredHeight)))
contentView.removeConstraint(widthConstraint)
return CGRectGetHeight(newFrame)
}
I know that with iOS 8 and dynamic UICollectionViewFlowLayout that the UICollectionViewCell's contentView handles constraints differently but is there something I'm missing here? What does one need to do to ensure that systemLayoutSizeFittingSize uses a particular width on a cell?
I also came across this post (Specifying one Dimension of Cells in UICollectionView using Auto Layout) and believe this might actually invalidate my question. Perhaps UICollectionViewFlowLayout is not designed for cells with only one dynamic dimension, but that still doesn't explain why the cell gives an unusual width.
I've faced same issue. The key is using priorities when getting systemLayoutSize.
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
if (!self.prototypeCell) {
self.prototypeCell = [TrainingMenuCell new];
self.prototypeCell.contentView.translatesAutoresizingMaskIntoConstraints = NO;
}
[self configureCell:self.prototypeCell forIndexPath:indexPath];
[self.prototypeCell setNeedsLayout];
[self.prototypeCell layoutIfNeeded];
CGFloat width = CGRectGetWidth(collectionView.frame) - 12;
CGSize fittingSize = UILayoutFittingCompressedSize;
fittingSize.width = width;
CGSize size = [self.prototypeCell.contentView systemLayoutSizeFittingSize:fittingSize withHorizontalFittingPriority:UILayoutPriorityRequired verticalFittingPriority:UILayoutPriorityDefaultLow];
return size;
}
In my case, it was not calculating width correctly because I was missing those two lines before calling systemLayoutSizeFittingSize
method:
[sizingCell setNeedsLayout];
[sizingCell layoutIfNeeded];
Spent hours to discover it so hope it could be helpful for others having similar issue.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With