title: Autoresize UICollectionView cells, Align cell to top
body: <p>I've a UICollectionView, with multiple sections and rows.
  Header and Footer views wherever necessary, of fixed size.
  Cells that are autoresizable</p>
  
  <p>The cell view are designed like :</p>
  
  <p>Green colour - ImageView</p>
  
  <p>Orange colour - Labels with <code>numberOfLines = 0</code>. </p>
  
  <p>The cell should expand it's size according to label <code>numberOfLines</code>.</p>
  
  <p>I've achieved this using this code in MyCustomCell :</p>
  
  <pre><code>override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -&gt; UICollectionViewLayoutAttributes {
          super.apply(layoutAttributes)
          let autoLayoutAttributes = super.preferredLayoutAttributesFitting(layoutAttributes)
          let targetSize = CGSize(width: Constants.screenWidth/3.5, height: 0)
          let autoLayoutSize = contentView.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: UILayoutPriority.required, verticalFittingPriority: UILayoutPriority.defaultLow)
          let autoLayoutFrame = CGRect(origin: autoLayoutAttributes.frame.origin, size: autoLayoutSize)
          autoLayoutAttributes.frame = autoLayoutFrame
          return autoLayoutAttributes
      }
  </code></pre>
  
  <p>The cells are autoresizing but the contentView (in cyan colour) are Centre aligned both vertically and horizontally.</p>
  
  <p><code>I need to make it vertically align to Top.</code></p>
  
  <p>I had the alignment problem with headers and footers too. For that i've subclassed <code>UICollectionViewFlowLayout</code></p>
  
  <pre><code>
  class MainCollectionViewFlowLayout: UICollectionViewFlowLayout {
  
      override func invalidationContext(forPreferredLayoutAttributes preferredAttributes: UICollectionViewLayoutAttributes, withOriginalAttributes originalAttributes: UICollectionViewLayoutAttributes) -&gt; UICollectionViewLayoutInvalidationContext {
  
          let context: UICollectionViewLayoutInvalidationContext = super.invalidationContext(forPreferredLayoutAttributes: preferredAttributes, withOriginalAttributes: originalAttributes)
  
          let indexPath = preferredAttributes.indexPath
          context.invalidateSupplementaryElements(ofKind: UICollectionView.elementKindSectionFooter, at: [indexPath])
          context.invalidateSupplementaryElements(ofKind: UICollectionView.elementKindSectionHeader, at: [indexPath])
  
          return context
      }
  
      override func layoutAttributesForElements(in rect: CGRect) -&gt; [UICollectionViewLayoutAttributes]? {
          let attributes = super.layoutAttributesForElements(in: rect)
  
          var topMargin = sectionInset.top
          var leftMargin = sectionInset.left
          var maxY: CGFloat = -1.0
          attributes?.forEach { layoutAttribute in
              guard layoutAttribute.representedElementCategory == .cell else {
                  return
              }
  
              if layoutAttribute.frame.origin.y &gt;= maxY {
                  leftMargin = sectionInset.left
                  topMargin = sectionInset.top
              }
  
              layoutAttribute.frame.origin.x = leftMargin
  
              leftMargin += layoutAttribute.frame.width + minimumInteritemSpacing
              maxY = max(layoutAttribute.frame.maxY , maxY)
          }
  
          return attributes
      }
  
  }
  
  </code></pre>
  
  <p>Here is an image to illustrate current situation. The cyan are contentView of cells. I've to make it align to Top.</p>
  
  <p><a href="https://i.stack.imgur.com/uGbzh.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/uGbzh.png" alt="enter image description here"></a></p>
  
  <p><strong>EDIT:</strong> 
  So i realised that <code>UICollectionViewFlowLayout</code> code was creating more bugs than fixing a problem. I added <code>layoutAttributesForElements</code> to left align my cell in case there is only one cell. What it actually did was align all of my cells to the left.
  Modified the code as </p>
  
  <pre><code>
  class MainCollectionViewFlowLayout: UICollectionViewFlowLayout {
      override func layoutAttributesForElements(in rect: CGRect) -&gt; [UICollectionViewLayoutAttributes]? {
  
          let attributes = super.layoutAttributesForElements(in: rect)
  
          if attributes?.count == 1 {
  
              if let currentAttribute = attributes?.first {
                  currentAttribute.frame = CGRect(x: self.sectionInset.left, y: currentAttribute.frame.origin.y, width: currentAttribute.frame.size.width, height: currentAttribute.frame.size.height)
              }
          }
          return attributes
      }
  }
  
  </code></pre>
  
  <p>Now my <code>UICollectionViewCell</code> are properly aligned to horizontal centre with exception to if only one cell which will be left aligned.</p>
  
  <p>Still no solution for vertical alignment.</p>