1 year ago

#73265

test-img

bao le

Custom UICollectionViewLayout, change cell height after image is downloaded inside a cell?

I'm using pinterest tutorial to achieve dynamic cell height according to image's size.

But there is a problem: After it downloaded the data, I send the URL to according cell. When the cell receives the link, it will download and change the picture. But from the tutorial, it calculate the image size way before its downloaded because it uses temp images that are already stored.

Inside cell Class:

var imageURL: String? {
        didSet {
            imageView.loadImage(self.imageURL ?? "")
        }
    }

Func to return image size height, this is in the ViewController class

    func collectionView(
        _ collectionView: UICollectionView, heightForPhotoAtIndexPath indexPath: IndexPath) -> CGFloat {
        return imgArr[indexPath.item].size.height + 100
        // it should be like this
        // guard let cell = self.collectionView.cellForItem(at: indexPath) as? LoansCell else {return}
        // return cell.photo.size.height

    }

Inside the UICollectionViewLayout class:

  override func prepare() {
        // 1    
        var section = 1 
        if isPartner {
            section = 0
        }
        let collectionViewItemCount = collectionView?.numberOfItems(inSection: section) ?? 0
        guard cache.isEmpty || collectionViewItemCount > cache.count, 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 section in 0..<collectionView.numberOfSections {
            for item in 0..<collectionView.numberOfItems(inSection: section) {
                let indexPath = IndexPath(item: item, section: section)
                let attributes: UICollectionViewLayoutAttributes

                // where it calls the protocol to get image h
                let photoHeight = delegate?.collectionView(
                    collectionView,
                    heightForPhotoAtIndexPath: indexPath) ?? 180
                let height = cellPadding * 2 + photoHeight
                let frame: CGRect
                var paddingForSection0: CGFloat = cellPadding // to make the horizontalView leading and trailling = screen.leading/trailing
                if section == 0 && !isPartner {
                    frame = CGRect(x: 0,
                                   y: yOffset[column] + headerHeight + cellPadding,
                                   width: contentWidth + insetLeftRight*2,
                                   height: height)
                    
                    contentHeight = frame.maxY
                    for column in 0..<numberOfColumns {
                        yOffset[column] = frame.maxY
                    }
                    paddingForSection0 = 0
                    column = 0
                } else {
                    // 4
                    var yPad = cellPadding * 2
                    if isPartner { // this is a temp approach
                        headerHeight = 0
                        yPad = cellPadding
                    }
                    frame = CGRect(x: xOffset[column] + insetLeftRight,
                                   y: yOffset[column] + headerHeight + yPad,
                                   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: paddingForSection0, dy: cellPadding)
                attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
                attributes.frame = insetFrame
                cache.append(attributes)
            }
        }
    }

The article I used: https://www.raywenderlich.com/4829472-uicollectionview-custom-layout-tutorial-pinterest

ios

swift

uicollectionview

uicollectionviewlayout

0 Answers

Your Answer

Accepted video resources