Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
//: Playground - noun: a place where people can play
import UIKit
import PlaygroundSupport
class LastRowCenteredLayout: UICollectionViewFlowLayout {
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
guard let originalAttributes = super.layoutAttributesForElements(in: rect) else { return nil }
guard originalAttributes.isEmpty == false else { return originalAttributes }
let finalAttributes = originalAttributes.map { $0.copy() as! UICollectionViewLayoutAttributes }
// Find maxY among all element attributes, then all elements line up with that maxY. Those elements are the ones from the last row
let maxY = finalAttributes.max { $0.frame.maxY < $1.frame.maxY }?.frame.maxY
let lastRowAttrs = finalAttributes.filter { $0.frame.maxY == maxY }
// If the elements in the last row don't sit flush against the right edge, then they need to be centered by shifting them a little to the right
if lastRowAttrs.frame.maxX < insettedFrame.maxX {
let shift = (insettedFrame.maxX - lastRowAttrs.frame.maxX) / 2.0
for attrs in lastRowAttrs {
attrs.frame = attrs.frame.offsetBy(dx: shift, dy: 0)
}
}
return finalAttributes
}
}
public class DataSource: NSObject, UICollectionViewDataSource {
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 32;
}
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
cell.backgroundColor = UIColor.green
return cell
}
}
extension CGRect {
func insettedBy(insets: UIEdgeInsets) -> CGRect {
return UIEdgeInsetsInsetRect(self, insets)
}
}
extension Array where Element: UICollectionViewLayoutAttributes {
var frame: CGRect {
return map { $0.frame }.reduce(self[0].frame, { $0.union($1) })
}
}
extension UICollectionViewFlowLayout {
var insettedFrame: CGRect {
guard let frame = collectionView?.frame else { return .zero }
return frame.insettedBy(insets: sectionInset)
}
}
let screen = UIView(frame: CGRect(x: 0, y: 0, width: 320, height: 500))
screen.backgroundColor = UIColor.white
let l = LastRowCenteredLayout()
l.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
l.itemSize = CGSize(width: 30, height: 30)
let c = UICollectionView(frame: screen.bounds, collectionViewLayout: l)
c.backgroundColor = UIColor.blue
c.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cell")
let ds = DataSource()
c.dataSource = ds
screen.addSubview(c)
PlaygroundPage.current.needsIndefiniteExecution = true
PlaygroundPage.current.liveView = screen
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment