Use Case:
- I have a
UICollectionViewto display products, let us call itproductsViewCollection(only one row with multipleProductCells). - Each
ProductCellmay has different height, but all of them have the same width. ProductCellmay be added at the run time.- I am using self resizing cells depending on the
AutoLayoutfor theProductCells. I have
UICollectionViewFlowLayoutcustom class to make the product cells alignment top.class TopLayout : UICollectionViewFlowLayout { override func awakeFromNib() { super.awakeFromNib(); self.scrollDirection = .horizontal; } override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { let attributesArray = super.layoutAttributesForElements(in: rect); if attributesArray != nil { for attributes in attributesArray! { if (attributes.representedElementKind == nil) { let rect : CGRect? = self.layoutAttributesForItem(at: attributes.indexPath)?.frame; if (rect != nil) { attributes.frame = rect!; } } } } return attributesArray; } override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? { let attributes = super.layoutAttributesForItem(at: indexPath); //let sectionInset : UIEdgeInsets = (self.collectionView?.collectionViewLayout as! UICollectionViewFlowLayout).sectionInset; if (indexPath.item >= 0) { attributes?.frame.origin.y = 0; } return attributes; }}
What is the problem?
- (1) I didn't find a way to determine the height for the
productsCollectionView. - (2) I didn't find a way to force the
productsCollectionViewto display only one row. - (3) Inserting a new
ProductCellinto theproductsCollectionViewleading to scroll to the first item!, I need to keep it at the same position.
What I tried?
- Tries for issue (1):
- Determining the width without the height will not work, because I need to determine the height for the
productsCollectionViewotherwise theProductCells will not appear. - Therefore I tried to set height constraint but the app has crashed
"The behavior of the UICollectionViewFlowLayout is not defined because the item height must be less than the height of the UICollectionView minus the section insets top and bottom values, minus the content insets top and bottom values.",productsCollectionViewdon't have insets (Horizontal UICollectionView single row layout). - I tried also to use
collectionView.contentSizewith height constraint to determine the height forproductsCollectionViewbut it didn't work because it will not have the final calculated size even if you calledlayoutIfNeededor any similar method (How to determine height of UICollectionView with FlowLayout and many other links). - I tried also to use
collectionView.collectionViewlayout.collectionViewContentSizewith height constraint to determine the height forproductsCollectionViewbut it didn't work, it will calculate the width correctly while the height will be determined according to theAutoLayoutconstraints not depending on the maximumProductCellheight, so I didn't find a way to determine the height automatically (How to determine height of UICollectionView with FlowLayout and many other links). - Therefore, finally I tried to change the height depending on the
ProductCells max height manually, I set larger height constraint for theproductsViewCollectionand in theMyViewControllerI calledlayoutAttributesForItemfor each item in theproductsViewCollectionto calculate eachProductCellheight. - It worked, but I should do the same thing if I need to insert any other products, but also this leaded to wrong behavior in the UI, the
productsCollectionViewwill expand for some of milliseconds then crop correctly :(.
- Determining the width without the height will not work, because I need to determine the height for the
- Tries for issue (2):
- Of course I made it horizontal but this is not enough, the flow layout will add products to the same column in case the sum of products heights is less than the
productsCollectionViewheight (Display one row in UICollectionView - Swift). - So I tried to set larger value for
minimumInteritemSpacingit worked but not 100% correctly, it will add extra space at the end (UICollectionView: One Row or Column). - I tried to make the
ProductCellheight same as theproductsCollectionViewheight using customUICollectionViewFlowLayoutclass in thelayoutAttributesForItemmethod, but it didn't work, heights changed but the cells at the same column, I don't know why!
- Of course I made it horizontal but this is not enough, the flow layout will add products to the same column in case the sum of products heights is less than the
- Tries for issue (3):
- I don't know why inserting new item leaded to scrolling, sometimes for the first item, sometimes before few items, sometimes it works correctly with strange resizing animation!. Anyway, I tried to disable my resizing
productsCollectionViewcode and nothing happened. - I tried to save current
productsCollectionView.contentOffsetthen apply it, and it worked only if I set theanimatedparameter equals totrue, otherwise it will be unspecified scrolling.
- I don't know why inserting new item leaded to scrolling, sometimes for the first item, sometimes before few items, sometimes it works correctly with strange resizing animation!. Anyway, I tried to disable my resizing
Note: Sorry for my bad English & Thanks.