Home > front end >  How to set Size for a specific cell when using dynamic size uicollectionView cell
How to set Size for a specific cell when using dynamic size uicollectionView cell

Time:10-29

I'm following this tutorial:

enter image description here

Basically a horizontal collectionView in section 1 and a vertical collectionView in section 2

My thought was putting a collectionView inside the first cell, which should have the size: CGSize(width: screen.width, height: 100)

But since I'm using the method from the link, I don't know how to give a specific size for the first cell. This is what I've tried:

enter image description here

CodePudding user response:

Disclaimer: As OP had asked a question earlier on how to create a Pinterest layout and I had suggested Raywenderlich tutorial in comments, I believe this question from OP is extension of that

Answer:

Looking at the design you added, I believe you are trying to add a CollectionView with a horizontal scroll as the first cell which spans the entire collection view width. Because you have subclassed the UICollectionViewFlowLayout you need to handle this special case in prepare method itself

    override func prepare() {
        // 1
        guard
            cache.isEmpty,
            let collectionView = collectionView
        else {
            return
        }
        // 2
        let columnWidth = contentWidth / CGFloat(numberOfColumns)
        var xOffset: [CGFloat] = []
        for column in 0..<numberOfColumns {
            xOffset.append(CGFloat(column) * columnWidth)
        }
        var column = 0
        var yOffset: [CGFloat] = .init(repeating: 0, count: numberOfColumns)

        // 3
        for item in 0..<collectionView.numberOfItems(inSection: 0) {
            let indexPath = IndexPath(item: item, section: 0)
            let attributes: UICollectionViewLayoutAttributes
            let photoHeight = delegate?.collectionView(
                collectionView,
                heightForPhotoAtIndexPath: indexPath) ?? 180
            let height = cellPadding * 2   photoHeight
            let frame: CGRect

            if item == 0 {
                frame = CGRect(x: 0,
                               y: yOffset[column],
                               width: columnWidth,
                               height: height)

                contentHeight = frame.maxY
                for column in 0..<numberOfColumns {
                    yOffset[column] = frame.maxY
                }
                column = 0
            }
            else {
                // 4
                frame = CGRect(x: xOffset[column],
                               y: yOffset[column],
                               width: columnWidth,
                               height: height)

                contentHeight = max(contentHeight, frame.maxY)
                yOffset[column] = yOffset[column]   height
                column = column < (numberOfColumns - 1) ? (column   1) : 0
            }

            let insetFrame = frame.insetBy(dx: cellPadding, dy: cellPadding)
            attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
            attributes.frame = insetFrame
            cache.append(attributes)
        }
    }

In your for item in 0..<collectionView.numberOfItems(inSection: 0) { I have added a special condition for handling if item == 0 { where in instead of using column width, I have used content width (as per your design you want first cell to cover the whole width of collection view)

Finally in your delegate method

extension PhotoStreamViewController: PinterestLayoutDelegate {
  func collectionView(
      _ collectionView: UICollectionView,
      heightForPhotoAtIndexPath indexPath:IndexPath) -> CGFloat {
          if indexPath.row == 0 {
              return 180 // whatever is the height of first cell
          }
          return photos[indexPath.item].image.size.height
      }
}

A word of caution

In your design I can see that you have added two section headers Header 1 and Header 2 I guess in that case your returning number of sections as at least 2, but the tutorial focuses on a single section collection view, if you notice

for item in 0..<collectionView.numberOfItems(inSection: 0) {

section 0 is hard coded, you might have to handle it dynamically if you wanna handle multiple sections and might need a lot of reworking around prepare

CodePudding user response:

A strategy you might follow to gain the ability to control the size of your collection items is to have your delegate for the UICollection view derive from UICollectionViewDelegateFlowLayout instead of just from UICollectionViewDelegate. By deriving from UICollectionViewDelegateFlowLayout your delegate can implement:

func collectionView(UICollectionView, layout: UICollectionViewLayout, sizeForItemAt: IndexPath) -> CGSize

And tell the system the size of the first item.

  • Related