Call collectionView(_ :layout:sizeForItemAt:) in Swift 4

Viewed 9875

I made the gallery using UICollectionView.

If you lower the screen, the image should continue to come out and stop at 20.

The code was constantly updated. However, the function collectionView (_: layout: sizeForItemAt :) that sets the size of the cell did not work. Therefore, only 20 images are displayed continuously.

On viewDidLoad()

if let layoutt = artCollectionView?.collectionViewLayout as? PinterestLayout
{
    layoutt.delegate = self
}

cell setting

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
    guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "HomeCollectionViewCell", for: indexPath) as? HomeCollectionViewCell,

    let arts = self.artList else { return HomeCollectionViewCell() }
    if arts.count > indexPath.row
    {
        let model = arts[indexPath.row]

        cell.imgView.sd_setImage(with: URLHelper.createEncodedURL(url: model.thumburl), completed: nil)
    }
    return cell
}

return cell size

extension HomeViewController : PinterestLayoutDelegate
{
    func collectionView(_ collectionView: UICollectionView, heightForPhotoAtIndexPath indexPath:IndexPath) -> CGFloat
    {
        return CGFloat(300.0)
    }
}

Currently, the function only executes once when the app starts. Do you know how to run that function every time I want?

3 Answers

You need to implement UICollectionViewDelegateFlowLayout. You can read more about the protocol here: UICollectionViewDelegateFlowLayout protocol

Example:

extension viewController: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: 50, height: 300)
    }
}

If you look at the prepare() method of PinterestLayout class, you can see the below code

guard
    cache.isEmpty == true,
    let collectionView = collectionView
    else {
      return
}

When you reload the colectionView the cache is no longer empty, so it returns back without altering the layout.

So just remove the cache value when prepare is called. Add removeAll() before guard

cache.removeAll()

Please follow the steps to install PinterestLayout in UICollectionView below.

Set PinterestLayout to your collection view.

let layout = PinterestLayout()
collectionView.collectionViewLayout = layout

Setup layout

layout.delegate = self
layout.cellPadding = 5
layout.numberOfColumns = 2

Implement methods of PinterestLayoutDelegate

extension CustomCollectionVC: PinterestLayoutDelegate {

    func collectionView(collectionView: UICollectionView,
                        heightForImageAtIndexPath indexPath: IndexPath,
                        withWidth: CGFloat) -> CGFloat {
        let image = images[indexPath.item]

        return image.height(forWidth: withWidth)
    }

    func collectionView(collectionView: UICollectionView,
                        heightForAnnotationAtIndexPath indexPath: IndexPath,
                        withWidth: CGFloat) -> CGFloat {
        let textFont = UIFont(name: "Arial-ItalicMT", size: 11)!                
        return "Some text".heightForWidth(width: withWidth, font: textFont)
    }
}

When data is loaded invalidate layout as well as reload data on collection view.

collectionView.collectionViewLayout.invalidateLayout()
collectionView.reloadData()

Observation:

func collectionView(_ collectionView: UICollectionView, heightForPhotoAtIndexPath indexPath:IndexPath) -> CGFloat

try this instead of above:

func collectionView(collectionView: UICollectionView,
                        heightForImageAtIndexPath indexPath: IndexPath,
                        withWidth: CGFloat) -> CGFloat
Related