I'm exploring IGListKit and I'm trying to achieve this with a IGListSectionController subclass:
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?
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
}
}