Use Case:
- I have a
UICollectionView
to display products, let us call itproductsViewCollection
(only one row with multipleProductCell
s). - Each
ProductCell
may has different height, but all of them have the same width. ProductCell
may be added at the run time.- I am using self resizing cells depending on the
AutoLayout
for theProductCell
s. I have
UICollectionViewFlowLayout
custom 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
productsCollectionView
to display only one row. - (3) Inserting a new
ProductCell
into theproductsCollectionView
leading 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
productsCollectionView
otherwise theProductCell
s 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."
,productsCollectionView
don't have insets (Horizontal UICollectionView single row layout). - I tried also to use
collectionView.contentSize
with height constraint to determine the height forproductsCollectionView
but it didn't work because it will not have the final calculated size even if you calledlayoutIfNeeded
or any similar method (How to determine height of UICollectionView with FlowLayout and many other links). - I tried also to use
collectionView.collectionViewlayout.collectionViewContentSize
with height constraint to determine the height forproductsCollectionView
but it didn't work, it will calculate the width correctly while the height will be determined according to theAutoLayout
constraints not depending on the maximumProductCell
height, 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
ProductCell
s max height manually, I set larger height constraint for theproductsViewCollection
and in theMyViewController
I calledlayoutAttributesForItem
for each item in theproductsViewCollection
to calculate eachProductCell
height. - 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
productsCollectionView
will 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
productsCollectionView
height (Display one row in UICollectionView - Swift). - So I tried to set larger value for
minimumInteritemSpacing
it worked but not 100% correctly, it will add extra space at the end (UICollectionView: One Row or Column). - I tried to make the
ProductCell
height same as theproductsCollectionView
height using customUICollectionViewFlowLayout
class in thelayoutAttributesForItem
method, 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
productsCollectionView
code and nothing happened. - I tried to save current
productsCollectionView.contentOffset
then apply it, and it worked only if I set theanimated
parameter 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.