The 8th Dnepropetrovsk iOS Practice Leaders Community Meet-up, which took place on Thursday, February 5th, was dedicated to collection view layouts.
Anatoliy Tukhtarov, iOS developer with 2+ years of experience made a presentation about:
— what UICollectionViewLayout is;
— when to create your own layout;
— creating your own layout from scratch;
— self-sizing collection view items;
— adding gestures to collection view (drag and drop, pinch to zoom, autoscroll, etc.)
During the presentation we created waterfall layout step by step and discuss appearing issues.
The presentation will be interesting for all developers who want to expand their knowledge about UICollectionView.
https://yadi.sk/d/eeEdMTiueTW9s — keynote
https://yadi.sk/i/DVDq3O3leTW8n — pdf
https://yadi.sk/i/t6-nw3uMeTW7D — pptx
6. UICollectionViewLayout
A kind of data source to provide visual information,
not data
Responsible for locations and sizes of all the cells,
supplementary and decoration views
Does not apply data to views
10. Documents application
• Landscape and portrait items A4 scale
• Multiple waterfall columns for iPad and iPhone
• Number of columns must be changed on device
rotation
• Drag and drop items like on home screen
• Autoscroll while dragging
v 0.1
Source code: https://github.com/swordfishyou/documents-app
11. Designing layout
• Number of columns in section
• Column width
• Cell size
• Cell frame
• Intercolumn and interline
spacings, etc.
• Cache all the possible values
layout delegate
data source
layout
13. Documents application
• Landscape and portrait items A4 scale
• Multiple waterfall columns for iPad and iPhone
• Number of columns must be changed on device
rotation
• Drag and drop items like on home screen
• Autoscroll while dragging
v 0.1
15. Documents application
• Landscape and portrait items A4 scale
• Multiple waterfall columns for iPad and iPhone
• Number of columns must be changed on device
rotation
• Drag and drop items like on home screen
• Autoscroll while dragging
v 0.1
16. Layout metrics
• Items’ sizes and attributes by index path
• Column metrics by section
• index
• section
• size
• items’ indexes in column
17. Cell frame
- (CGRect)itemFrameAtIndexPath:(NSIndexPath *)indexPath {
CGRect frame;
frame.size = ...; /// use cached value
CGFloat topOffset = 0.0;
for (NSInteger section = 0; section < indexPath.section; ++section) {
/// Shift vertically by sections above
}
NSInteger numberOfColumnsInSection = ...;
NSInteger itemColumn = indexPath.item % numberOfColumnsInSection;
FLSColumnLayoutMetrics *columnMetrics = ...;
for (NSInteger item = 0; item < indexPath.item; ++item) {
if ([columnMetrics.itemIndexes containsIndex:item]) {
/// Shift vertically by items in column
}
}
frame.origin.y = topOffset;
CGFloat leftOffset = itemColumn * self.minimumItercolumnSpacing;
for (NSInteger column = 0; column < itemColumn; ++column) {
/// Shift horizontally by columns left
}
/// Centre cell in item’s column
return frame;
}
18. Documents application
• Landscape and portrait items A4 scale
• Multiple waterfall columns for iPad and iPhone
• Number of columns must be changed on device
rotation
• Drag and drop items like on home screen
• Autoscroll while dragging
v 0.1
20. Documents application
• Landscape and portrait items A4 scale
• Multiple waterfall columns for iPad and iPhone
• Number of columns must be changed on device
rotation
• Drag and drop items like on home screen
• Autoscroll while dragging
v 0.1
21. Drag and drop
• Consider to use gestures controller or state
machine
• Layout is responsible for changing frame of a
dragging item
• Data source is responsible for handling motion
actions (like reorder array, etc.)
General ideas
22. Drag and drop
- (void)beginDraggingItemAtIndexPath:(NSIndexPath *)indexPath {
/// Snapshot cell and index path
self.draggingIndexPath = indexPath;
UICollectionViewCell *cell = ...;
UIView *snapshot = [cell snapshotViewAfterScreenUpdates:NO];
self.draggingView = snapshot;
[self.collectionView addSubview:self.draggingView];
/// Calculate drag bounds if needed
[UIView animateWithDuration:animationDuration
animations:^{
/// Indicate dragging item with animation
} completion:^(BOOL finished) {
/// Invalidate layout
}];
}
Begin dragging
23. Drag and drop
- (void)handlePanGesture:(UIPanGestureRecognizer *)gesture {
switch (gesture.state) {
case UIGestureRecognizerStateChanged:{
[self scheduleDraggingHoldTimer];
/// Calculate new centre of the dragging view
CGPoint translation = [gesture translationInView:self.collectionView];
CGPoint diff = ...;
self.lastTranslation = translation;
CGPoint center = ...;
[self constrainPointToDragBounds:¢er];
self.draggingView.center = center;
/// Trigger autoscroll
break;
}
case UIGestureRecognizerStateEnded:
/// Invalidate timers
break;
}
}
Handle pan gesture
24. Drag and drop
- (void)handleDraggindHold:(NSTimer *)timer {
FLSDataSource *dataSource = self.collectionView.dataSource;
NSIndexPath *newIndexPath = [self.collectionView
indexPathForItemAtPoint:self.draggingView.center];
if (newIndexPath != nil &&
![newIndexPath isEqual:self.draggingIndexPath]) {
BOOL canMove = ...; /// Use data source
if (canMove) {
self.draggingIndexPath = newIndexPath;
[dataSource collectionView:self.collectionView
moveItemAtIndexPath:self.lastSourceIndexPath
toIndexPath:newIndexPath isHeld:YES];
self.lastSourceIndexPath = newIndexPath;
/// Invalidate layout
}
}
}
Handle hold
25. Documents application
• Landscape and portrait items A4 scale
• Multiple waterfall columns for iPad and iPhone
• Number of columns must be changed on device
rotation
• Drag and drop items like on home screen
• Autoscroll while dragging
v 0.1
26. Autoscroll
• Consider to use CADisplayLink instead of
NSTimer
• Invalidate dragging hold timer while autoscrolling
• Calculate autoscroll direction and velocity while
dragging
• Calculate dragging view’s frame and collection
view’s contentOffset
28. Autoscroll
CGFloat distance = rintf(self.autosctollVelocity / 60.0);
switch (self.autoscrollDirection) {
/// Visually stop autoscroll if bottom of the content was
reached
case FLSAutoscrollDirectionDown: {
break;
}
/// Visually stop autoscroll if top of the content was reached
default:
break;
}
CGPoint translation = CGPointMake(0, distance);
CGPoint newCenter = ...;
[self constrainPointToDragBounds:&newCenter];
self.draggingView.center = newCenter;
self.collectionView.contentOffset = ...;
Handle autoscroll
29. Recap
• Cache all the possible values: calculate once and
reuse
• Auto layout is your friend
• Invalidate layout rationally
• Measure, measure and… measure
30. More information
WWDC 2014 — Session 232
Advanced User Interfaces with Collection View
Source code: https://developer.apple.com/wwdc/resources/sample-code/
WWDC 2014 — Session 226
What's New in Table and Collection Views
Collection View Programming Guide for iOS
Creating Custom Layout
Yalantis
Excel Page Layout for Collection View
http://yalantis.com/blog/data-grid-with-freeze-columns-play-by-your-rules/
WWDC 2012 — Session 219
Advanced Collection Views and Building Custom Layout
7th iOS Practice Leaders
Introduction to Auto Layout
Presentation