Skip to content

Instantly share code, notes, and snippets.

@gwennguihal
Last active February 25, 2019 08:01
Show Gist options
  • Save gwennguihal/0d4cba8500a480b7262b92fa0ba176d1 to your computer and use it in GitHub Desktop.
Save gwennguihal/0d4cba8500a480b7262b92fa0ba176d1 to your computer and use it in GitHub Desktop.
open class VerticalCollectionViewLayout: UICollectionViewFlowLayout {
unowned fileprivate let collectionViewData: CollectionData
fileprivate var cachedItemAttributes = [IndexPath:UICollectionViewLayoutAttributes]()
fileprivate var globalOffset = CGPoint()
var contentSize = CGSize()
public init(collectionViewData: CollectionData) {
self.collectionViewData = collectionViewData
super.init()
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override open func prepare() {
super.prepare()
// To be sure that each descriptor contains an indexPath
collectionViewData.computeIndices()
// reset
globalOffset = CGPoint()
cachedItemAttributes.removeAll()
collectionViewData.sections.enumerated().forEach { (sectionIndex, sectionDescriptor) in
// cast SectionDescriptor
guard let sectionDescriptor = collectionViewData.sections[sectionIndex] as? SectionDescriptor else {
return
}
sectionDescriptor.cells.compactMap { $0.indexPath }.forEach { indexPath in
// copy super itemAttributes
guard let itemAttributes = super.layoutAttributesForItem(at: indexPath)?.copy() as? UICollectionViewLayoutAttributes else {
return
}
// offset attributes by sum of verticalSpaces
itemAttributes.frame = itemAttributes.frame.offsetBy(dx: 0, dy: globalOffset.y)
cachedItemAttributes[indexPath] = itemAttributes
// add vertical space from the dictionary stored in the section descriptor
// currently vertical space are added after cell, but it's possible to add space before cell width -1 index
if let verticalSpace = sectionDescriptor.verticalSpaces[indexPath.item] {
globalOffset.y += verticalSpace
}
}
}
// offet content Size by global offset
contentSize = super.collectionViewContentSize
contentSize.height += globalOffset.y
}
open override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
return cachedItemAttributes[indexPath]
}
open override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
return cachedItemAttributes.values.filter { rect.intersects($0.frame) }
}
open override var collectionViewContentSize: CGSize {
return contentSize
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment