yoninja
yoninja

Reputation: 1962

How to make custom IGListSectionController

I'm exploring IGListKit and I'm trying to achieve this with a IGListSectionController subclass:

enter image description here

Basically, each colored area is one UICollectionViewCell. I already done something that doesn't have the green area. But, what I want is the layout in the example above. How do I do this?

Upvotes: 1

Views: 564

Answers (1)

yoninja
yoninja

Reputation: 1962

I found the answer and it was actually pretty simple. So, (like in UICollectionView) it must be set with a custom UICollectionViewLayout. So I have something like this:

let collectionView:IGListCollectionView = {
    let layout = MyCustomLayout()
    let view = IGListCollectionView(frame: .zero, collectionViewLayout: layout)
    return view
}() 

Here's what my custom layout looks like:

protocol MyCustomLayoutDelegate {
    func heightForItem(inCollectionView: UICollectionView, at position: Int) -> CGFloat
}

class MyCustomLayout: UICollectionViewLayout, MyCustomLayoutDelegate {

    var delegate:MyCustomLayoutDelegate?

    private var cache = [UICollectionViewLayoutAttributes]()

    private var aHeight:CGFloat = 0

    private var contentWidth:CGFloat {
        return collectionView!.bounds.width
    }

    override func prepare() {

        if cache.isEmpty {

            var yOffset:CGFloat = 0

            for section in 0 ..< collectionView!.numberOfSections {
                let contentHeight = (delegate ?? self).heightForItem(inCollectionView: collectionView!, at: section)
                let leftAreaWidth = contentHeight - 1
                let topAreaHeight:CGFloat = 20.0
                let bottomAreaHeight = contentHeight - topAreaHeight - 1
                let bottomAreaWidth = contentWidth - leftAreaWidth

                let leftAreaIndexPath = IndexPath(item: 0, section: section)
                let topAreaIndexPath = IndexPath(item: 1, section: section)
                let bottomAreaIndexPath = IndexPath(item: 2, section: section)

                let leftAreaFrame = CGRect(x: 0, y: yOffset, width: leftAreaWidth, height: leftAreaWidth)
                let topAreaFrame = CGRect(x: leftAreaWidth, y: yOffset, width: bottomAreaWidth, height: topAreaHeight)
                let bottomAreaFrame = CGRect(x: leftAreaWidth, y: yOffset + topAreaHeight, width: bottomAreaWidth, height: bottomAreaHeight)

                let leftAreaAttributes = UICollectionViewLayoutAttributes(forCellWith: leftAreaIndexPath)
            leftAreaAttributes.frame = leftAreaFrame
            cache.append(leftAreaAttributes)

                let topAreaAttributes = UICollectionViewLayoutAttributes(forCellWith: topAreaIndexPath)
            topAreaAttributes.frame = topAreaFrame
            cache.append(topAreaAttributes)

                let bottomAreaAttributes = UICollectionViewLayoutAttributes(forCellWith: bottomAreaIndexPath)
            bottomAreaAttributes.frame = bottomAreaFrame
            cache.append(bottomAreaAttributes)

                yOffset += contentHeight
            }

            aHeight = yOffset
        }
    }

    override var collectionViewContentSize: CGSize {
        return CGSize(width: contentWidth, height: aHeight)
    }

    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {

        return cache.filter {
            $0.frame.intersects(rect)
        }
    }

    override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {

        return cache.first {
            $0.indexPath == indexPath
        }

    }

    override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {

        if let oldWidth = collectionView?.bounds.width {
            return oldWidth != newBounds.width
        }

        return false
    }

    override func invalidateLayout() {
        super.invalidateLayout()

        cache = []
        aHeight = 0
    }

    //Delegate
    internal func heightForItem(inCollectionView: UICollectionView, at postion: Int) -> CGFloat {
        return 0
    }
}

Upvotes: 2

Related Questions