class CollectionViewFlowLayoutLeftAlign: UICollectionViewFlowLayout {
override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
guard let attributes = super.layoutAttributesForElementsInRect(rect) else {
return nil
}
var attributesToReturn = attributes.map { $0.copy() as! UICollectionViewLayoutAttributes }
for (index, attr) in attributes.enumerate() where attr.representedElementCategory == .Cell {
attributesToReturn[index] = layoutAttributesForItemAtIndexPath(attr.indexPath) ?? UICollectionViewLayoutAttributes()
}
return attributesToReturn
}
override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? {
guard let currentAttributes = super.layoutAttributesForItemAtIndexPath(indexPath)?.copy() as? UICollectionViewLayoutAttributes,
let viewWidth = collectionView?.frame.width else {
return nil
}
let sectionInsetsLeft = sectionInsets(at: indexPath.section).left
guard indexPath.item > 0 else {
currentAttributes.frame.origin.x = sectionInsetsLeft
return currentAttributes
}
let prevIndexPath = NSIndexPath(forItem: indexPath.item - 1, inSection: indexPath.section)
guard let prevFrame = layoutAttributesForItemAtIndexPath(prevIndexPath)?.frame else {
return nil
}
let validWidth = viewWidth - sectionInset.left - sectionInset.right
let currentColumnRect = CGRectMake(sectionInsetsLeft, currentAttributes.frame.origin.y, validWidth, currentAttributes.frame.height)
guard CGRectIntersectsRect(prevFrame, currentColumnRect) else {
currentAttributes.frame.origin.x = sectionInsetsLeft
return currentAttributes
}
let prevItemTailX = prevFrame.origin.x + prevFrame.width
currentAttributes.frame.origin.x = prevItemTailX + minimumInteritemSpacing(at: indexPath.section)
return currentAttributes
}
private func sectionInsets(at index: Int) -> UIEdgeInsets {
guard
let collectionView = collectionView,
let delegate = collectionView.delegate as? UICollectionViewDelegateFlowLayout else {
return self.sectionInset
}
return delegate.collectionView?(collectionView, layout: self, insetForSectionAtIndex: index) ?? self.sectionInset
}
private func minimumInteritemSpacing(at index: Int) -> CGFloat {
guard
let collectionView = collectionView,
let delegate = collectionView.delegate as? UICollectionViewDelegateFlowLayout else {
return self.minimumInteritemSpacing
}
return delegate.collectionView?(collectionView, layout: self, minimumInteritemSpacingForSectionAtIndex: index) ?? self.minimumInteritemSpacing
}
}