2

Use Case:

  • I have a UICollectionView to display products, let us call it productsViewCollection (only one row with multiple ProductCells).
  • 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 the ProductCells.
  • 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 the productsCollectionView 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 the ProductCells 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 for productsCollectionView but it didn't work because it will not have the final calculated size even if you called layoutIfNeeded 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 for productsCollectionView but it didn't work, it will calculate the width correctly while the height will be determined according to the AutoLayout constraints not depending on the maximum ProductCell 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 ProductCells max height manually, I set larger height constraint for the productsViewCollection and in the MyViewController I called layoutAttributesForItem for each item in the productsViewCollection to calculate each ProductCell 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 :(.
  • 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 the productsCollectionView height using custom UICollectionViewFlowLayout class in the layoutAttributesForItem method, but it didn't work, heights changed but the cells at the same column, I don't know why!
  • 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 the animated parameter equals to true, otherwise it will be unspecified scrolling.

Note: Sorry for my bad English & Thanks.

Mu Sa
  • 211
  • 2
  • 8

0 Answers0