collection view layout

30
Collection view custom layout Waterfall layout case study iOS Practice Leaders Anatoly Tukhtarov

Upload: ciklum

Post on 15-Jul-2015

392 views

Category:

Technology


3 download

TRANSCRIPT

Page 1: Collection view layout

Collection view custom

layoutWaterfall layout case study

iOS Practice Leaders

Anatoly Tukhtarov

Page 2: Collection view layout

Introduction

UICollectionView is available since iOS 6

Allows present collections of data with custom

layout

Still in development

Page 3: Collection view layout

Agenda

• UICollectionView and its views

• UICollectionViewLayout and its friends

• Waterfall collection view layout

Page 4: Collection view layout

UICollectionView views

Managed by collection view’s data source (i.e. represent

some data)

• Cells — UICollectionViewCell

• Supplementary views (section’s or collection view’s headers, footers, etc.) —

UICollectionReusableView

Managed by collection view’s layout

• Decoration views (items separators, shadows, borders, etc.) —

UICollectionReusableView

Only cells are selectable

Page 5: Collection view layout

How does collection view

know how to place its

views?UICollectionViewLayout

Page 6: Collection view layout

UICollectionViewLayoutA 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

Page 7: Collection view layout

UICollectionViewLayoutClasses

UICollectionViewLayoutAttributes

• view’s layout attributes like frame, alpha,

transform, etc.

• created and configured by layout

• must adopt NSCopying protocol

• must override equality methods

(-hash, -isEqual:)

• applied by collection view

Page 8: Collection view layout

UICollectionViewLayoutClasses

UICollectionViewLayoutInvalidationContext

• available since iOS 7

• declares which parts of layout need to be updated

on layout invalidation

• capital update for iOS 8

Page 9: Collection view layout

Waterfall layoutDocuments list application

Page 10: Collection view layout

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

Page 11: Collection view layout

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

Page 12: Collection view layout

Building layout- (void)buildLayout {

if (self.isPreparingLayout) {

return;

}

self.preparingLayout = YES;

/// Calculate items sizes and columns metrics

if (!self.isLayoutDataValid) {

[self buildLayoutFromDataSource];

self.layoutDataValid = YES;

}

self.layoutSize = CGSizeZero;

[self.layoutAttributes removeAllObjects];

/// Calculate (reuse) layout attributes

[self calculateLayoutAttributes];

self.preparingLayout = NO;

}

Page 13: Collection view layout

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

Page 14: Collection view layout

Cell size (self-sizing cells)

- (CGSize)collectionView:(UICollectionView *)collectionView

sizeFittingSize:(CGSize)fittingSize

forItemAtIndexPath:(NSIndexPath *)indexPath {

FLSCollectionViewCell *cell = [self collectionView:collectionView

cellForItemAtIndexPath:indexPath];

CGRect frame = cell.frame;

frame.size = fittingSize;

cell.frame = frame;

CGSize size;

[cell layoutIfNeeded];

size = [cell.contentView

systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];

[cell removeFromSuperview];

return size;

}

Auto layouts case

Page 15: Collection view layout

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

Page 16: Collection view layout

Layout metrics

• Items’ sizes and attributes by index path

• Column metrics by section

• index

• section

• size

• items’ indexes in column

Page 17: Collection view layout

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;

}

Page 18: Collection view layout

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

Page 19: Collection view layout

Layout invalidation@interface FLSCollectionViewLayoutInvalidationContext :

UICollectionViewLayoutInvalidationContext

@property (nonatomic, assign) BOOL invalidateLayoutMetrics;

@end

+ (Class)invalidationContextClass;

- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds;

- (UICollectionViewLayoutInvalidationContext *)

invalidationContextForBoundsChange:(CGRect)newBounds;

- (void)invalidateLayoutWithContext:

(FLSCollectionViewLayoutInvalidationContext *)context;

Page 20: Collection view layout

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

Page 21: Collection view layout

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

Page 22: Collection view layout

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

Page 23: Collection view layout

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:&center];

self.draggingView.center = center;

/// Trigger autoscroll

break;

}

case UIGestureRecognizerStateEnded:

/// Invalidate timers

break;

}

}

Handle pan gesture

Page 24: Collection view layout

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

Page 25: Collection view layout

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

Page 26: Collection view layout

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

Page 27: Collection view layout

Autoscroll

CGRect autoscrollFrame = UIEdgeInsetsInsetRect(self.collectionView.bounds,

self.autoscrollTriggerInsets);

CGPoint location = [gesture locationInView:self.collectionView];

CGFloat top = CGRectGetMinY(autoscrollFrame);

CGFloat bottom = CGRectGetMaxY(autoscrollFrame);

if (location.y < top) {

self.autosctollVelocity = 10 * (top - location.y);

[self scheduleAutoscrollTimerWithDirection:FLSAutoscrollDirectionUp];

} else if (location.y > bottom) {

self.autosctollVelocity = 10 * (location.y - bottom);

[self scheduleAutoscrollTimerWithDirection:FLSAutoscrollDirectionDown];

} else {

[self invalidateAutoscrollTimer];

}

Trigger autoscroll

Page 28: Collection view layout

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

Page 29: Collection view layout

Recap

• Cache all the possible values: calculate once and

reuse

• Auto layout is your friend

• Invalidate layout rationally

• Measure, measure and… measure

Page 30: Collection view layout

More informationWWDC 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