Skip to content

Instantly share code, notes, and snippets.

@kflip
Last active September 6, 2017 12:49
Show Gist options
  • Save kflip/52ec15ddb07aa830d583856909fbefd4 to your computer and use it in GitHub Desktop.
Save kflip/52ec15ddb07aa830d583856909fbefd4 to your computer and use it in GitHub Desktop.
//
// OneLineForEachSectionLayout.swift
//
// Created by Philipp Kinschel on 28/11/2016.
//
//
//
// very basic solution to layout one section in one line without linebreaks
// TODO: find name for the class
//
import UIKit
class OneLineForEachSectionLayout: UICollectionViewLayout {
var itemSize = CGSize(width: 50, height: 50)
var minimumInteritemSpacing: CGFloat = 10
var minimumLineSpacing: CGFloat = 10
private var cachedContentSize: CGSize = .zero
private var cachedLayoutAttributes = [IndexPath: UICollectionViewLayoutAttributes]()
override var collectionViewContentSize: CGSize {
return self.cachedContentSize
}
override func prepare() {
guard let collectionView = collectionView else { return }
cachedContentSize = contentSize()
cachedLayoutAttributes = [IndexPath: UICollectionViewLayoutAttributes]()
for section in 0..<collectionView.numberOfSections {
for item in 0..<collectionView.numberOfItems(inSection: section) {
let indexPath = IndexPath(item: item, section: section)
if let layoutAttributes = layoutAttributesForItem(at: indexPath) {
cachedLayoutAttributes[indexPath] = layoutAttributes
}
}
}
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
return self.cachedLayoutAttributes.filter { (indexPath, layoutAttributes) -> Bool in
return layoutAttributes.frame.intersects(rect)
}.map({ (indexPath, layoutAttributes) -> UICollectionViewLayoutAttributes in
return layoutAttributes
})
}
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
let layoutAttributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
layoutAttributes.frame = CGRect(origin: originForItem(at: indexPath), size: itemSize)
return layoutAttributes
}
private func originForItem(at indexPath: IndexPath) -> CGPoint {
return CGPoint(x: horizontalOffsetForItem(at: indexPath), y: verticalOffsetForItem(at: indexPath))
}
private func horizontalOffsetForItem(at indexPath: IndexPath) -> Int {
return indexPath.row * Int(itemSize.width + minimumInteritemSpacing)
}
private func verticalOffsetForItem(at indexPath: IndexPath) -> Int {
return indexPath.section * Int(itemSize.height + minimumLineSpacing)
}
private func contentSize() -> CGSize {
guard let collectionView = collectionView else { return .zero }
let rows = maxNumberOfRows()
return CGSize(width: rows * Int(itemSize.width + minimumInteritemSpacing),
height: collectionView.numberOfSections * Int(itemSize.height + minimumLineSpacing))
}
/// iterates through sections to determine largest amount of items per section
private func maxNumberOfRows() -> Int {
guard let collectionView = collectionView else { return 0 }
var maxRows = 0
for section in 0..<collectionView.numberOfSections {
maxRows = max(maxRows, collectionView.numberOfItems(inSection: section))
}
return maxRows
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment