Dimitri James Tsiflitzis
CocoheadsSKG
UICollectionView is an object that manages an ordered collection of data items and presents them using customisable layouts.
It's powerful, with support for scrolling, tap recognition, layout changes, and performance. There is also a high quality ecosystem of third party libraries built on top of it.
I dare say that every screen in an app could be a collection view.
CocoheadsSKG
CocoheadsSKG
Unlike UITableView, UICollectionView gives you the freedom to specify your own layout.
You can render your datasource in any way you please.
It could be argued that you don't really need to use a table view ever again
CocoheadsSKG
Documentation is available from Apple, and other sources.
Today we will be going over a template you can use for your own layout along with some layouts of varying complexity.
CocoheadsSKG
When it comes down to it, the layout is responsible for two things:
CocoheadsSKG
var frame: CGRect // The frame rectangle of the item.
var bounds: CGRect // The bounds of the item.
var center: CGPoint // The center point of the item.
var size: CGSize // The size of the item.
var transform3D: CATransform3D // The 3D transform of the item.
var transform: CGAffineTransform // The affine transform of the item.
var alpha: CGFloat // The transparency of the item.
var zIndex: Int // Specifies the item’s position on the z axis.
var isHidden: Bool // Determines whether the item is currently displayed.
CocoheadsSKG
UIKit (Cocoa?) will call the following methods in the following order:
CocoheadsSKG
CocoheadsSKG
CocoheadsSKG
var contentSize: CGSize = .zero
var cachedAttributes = [IndexPath: UICollectionViewLayoutAttributes]()
override func prepare() {
contentSize = .zero // Clear out previous results
cachedAttributes = [IndexPath: UICollectionViewLayoutAttributes]()
for section in 0 ..< collectionView.numberOfSections {
for item in 0 ..< collectionView.numberOfItems(inSection: section) {
let itemFrame = // ...Compute the frame of your cell...
// Create the layout attributes and set the frame
let indexPath = IndexPath(item: item, section: section)
let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
attributes.frame = itemFrame
// Store the results
cachedAttributes[indexPath] = attributes
}
}
contentSize = // Store computed content size
}CocoheadsSKG
private var contentSize: CGSize = .zero
override var collectionViewContentSize: CGSize {
return contentSize
}CocoheadsSKG
var cachedAttributes = [IndexPath: UICollectionViewLayoutAttributes]()
override func layoutAttributesForElements(in rect: CGRect)
-> [UICollectionViewLayoutAttributes]? {
var attributeList = [UICollectionViewLayoutAttributes]()
for (_, attributes) in cachedAttributes {
if attributes.frame.intersects(rect) {
attributeList.append(attributes)
}
}
return attributeList
}CocoheadsSKG
CocoheadsSKG
Your collection view may also ask for layout attributes at specific index paths at any given time:
CocoheadsSKG
var cachedAttributes = [IndexPath: UICollectionViewLayoutAttributes]()
override func layoutAttributesForItem(at indexPath: IndexPath)
-> UICollectionViewLayoutAttributes? {
return cachedAttributes[indexPath]
}CocoheadsSKG
Return the size of the content area in collectionViewContentSize
Return UICollectionViewLayoutAttributes with set frames in:
layoutAttributesForElements(in:)
layoutAttributesForItem(at:),
layoutAttributesForSupplementaryView(ofKind:at:)
layoutAttributesForDecorationView(ofKind:at:)
CocoheadsSKG
CocoheadsSKG
CocoheadsSKG
CocoheadsSKG