Search code examples
iosswiftuicollectionviewuicollectionviewlayout

Single CollectionView with multiple CollectionViewLayout.why Layout is mess up?


I have Single UICollectionView , and I want to Apply Two different layout dynamically.

  1. UICollectionViewFlowLayout : A Layout with same size cell and circle image.

    var flowLayout: UICollectionViewFlowLayout {
        let flowLayout = UICollectionViewFlowLayout()
    
        flowLayout.itemSize = CGSize(width: UIScreen.main.bounds.width/3, height: 140)
        flowLayout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0)
        flowLayout.scrollDirection = UICollectionViewScrollDirection.vertical
        flowLayout.minimumInteritemSpacing = 0.0
    
        return flowLayout
    }
    
  2. Pintrest Layout : https://www.raywenderlich.com/392-uicollectionview-custom-layout-tutorial-pinterest

For Example : when user Click on Profile Button FlowLayout will be Apllied and Cell Appear with image in Circle Shape. when user click on Picture button pintrest layout will be Applied and cell Appear with image in Rectangle shape with dynamic height.

enter image description here

intially CollectionView have 1.flowLayout and it appears perfectly.but when I click on Picture button Pintrest layout is messed up with previous layout as shown in above image.

Following is Code For changing Layout.

if isGrid {
    let horizontal = flowLayout
    recentCollectionView.setCollectionViewLayout(horizontal, animated: true)
    recentCollectionView.reloadData()
}
else {
    let horizontal = PinterestLayout()
    horizontal.delegate = self
    recentCollectionView.setCollectionViewLayout(horizontal, animated: true)
    recentCollectionView.reloadData()
}

ViewHiarchy:

I have main Collection-view that Contain header and one bottom cell.cell contain other Collection-view to which I am Applying multiple layout.I have Two Different cell for each layout.I want bottom cell size equal to content Collection-view Content size so user can Scroll entire main collection-view vertically.

 func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        var cell : UICollectionViewCell!

        switch isGrid {
        case true:
            cell = collectionView.dequeueReusableCell(withReuseIdentifier: "SearchProfileCell", for: indexPath)
            if let annotateCell = cell as? SearchProfileCell {
                annotateCell.photo = photos[indexPath.item]
            }
        case false:
             cell = collectionView.dequeueReusableCell(withReuseIdentifier: "AnnotatedPhotoCell", for: indexPath)

            if let annotateCell = cell as? AnnotatedPhotoCell {
                annotateCell.cellwidth = collectionView.contentSize.width/3
                annotateCell.photo = photos[indexPath.item]

            }
        }

        cell.contentView.layer.cornerRadius = 0
        return cell
    }

Code of profile and picture button Action.

@IBAction func pictureClick(sender:UIButton) {
        isGrid = false
        self.searchCollectionView.reloadData()
    }

    @IBAction func profilClick(sender:UIButton) {
        isGrid = true
        self.searchCollectionView.reloadData()
    }

Solution

  • Why you are using two different layout even though you can achieve same Result with pintrestLayout. https://www.raywenderlich.com/392-uicollectionview-custom-layout-tutorial-pinterest.

    Check pintrestLayout carefully , it have Delegate for Dynamic height.

     let photoHeight = delegate.collectionView(collectionView, heightForPhotoAtIndexPath: indexPath)
    

    if you return static height here , your pintrest layout become GridLayout(your First Layout).

    if you want pintrest layout as work for both layout , you need to declare same Boolean(isGrid) in pintrest layout.and use this boolean to return UICollectionViewLayoutAttributes

    more important raywenderlich pintrest layout uses cache to store layout attribute.you have to remove cache object before applying other layout.

    Check in this tutorial , how same layout used for grid,list and linear. https://benoitpasquier.com/optimise-uicollectionview-swift/

    what you need in your layout.

     var isGrid : Bool = true {
            didSet {
                if isGrid != oldValue {
                    cache.removeAll()
                    self.invalidateLayout()
                }
            }
        }