More Related Content Similar to iOS Combining Touch and Animation Similar to iOS Combining Touch and Animation (8) iOS Combining Touch and Animation1. TOUCH
&
ANIMATION
Saturday, April 6, 13 1
2. René Cacheaux
Senior iOS Engineer
rene.cacheaux@mutualmobile.com
Saturday, April 6, 13 2
3. Touch can
control
anything
Saturday, April 6, 13 3
9. Where to
begin?
Saturday, April 6, 13 9
11. 1 Location in View:
global
Metrics 2 Number of Touches
3 Location of
Touch in View:
Saturday, April 6, 13 11
12. 1 Translation in View:
Pan
2 Velocity in View:
Saturday, April 6, 13 12
13. 1 Scale
Pinch
2 Velocity
Saturday, April 6, 13 13
14. Long
press
Saturday, April 6, 13 14
15. What to
Control
Saturday, April 6, 13 15
17. Core animation
Programming Guide
WWDC Videos
Headers
Saturday, April 6, 13 17
19. Quartz 2D
Programming Guide
WWDC Videos
Headers
Saturday, April 6, 13 19
21. Core Image
Programming Guide
WWDC Videos
Headers
Saturday, April 6, 13 21
27. 1 Para-what?
2 Parallaxing Rainforest
3 Show Me the Money
Saturday, April 6, 13 27
28. 1 Para-what?
2 Parallaxing Rainforest
3 Show Me the Money
Saturday, April 6, 13 28
29. 1 Para-what?
2 Parallaxing Rainforest
3 Show Me the Money
Saturday, April 6, 13 29
31. 1 Para-what?
2 Parallaxing Rainforest
3 Show Me the Money
Saturday, April 6, 13 31
33. Banner
Parallaxing Cell
Components
Banner
Parallaxing Cell
Saturday, April 6, 13 33
34. rainforest
PXColletionViewController
UIView UICollectionView PXCollectionViewLayout
PXCollectionViewCell
PXCollectionViewCell UICollectionReusableView
UICollectionReusableView
PXCollectionViewCell
PXCollectionViewCell UICollectionReusableView
PXBannerView
Saturday, April 6, 13 34
37. UI Collection View
UICollectionViewDataSource
UICollectionView UICollectionViewLayout
UICollectionViewDelegate
UICollectionViewCell UICollectionReusableView
UICollectionViewCell UICollectionReusableView
UICollectionViewCell UICollectionReusableView
UICollectionViewCell UICollectionReusableView
Saturday, April 6, 13 37
38. UI Collection View
3
UICollectionViewDataSource
1
UICollectionView
2
UICollectionViewLayout
UICollectionViewDelegate
UICollectionViewCell UICollectionReusableView
UICollectionViewCell UICollectionReusableView
UICollectionViewCell UICollectionReusableView
UICollectionViewCell UICollectionReusableView
Saturday, April 6, 13 38
39. Collection View
UICollectionViewDataSource
1
UICollectionView UICollectionViewLayout
UICollectionViewDelegate
UICollectionViewCell UICollectionReusableView
UICollectionViewCell UICollectionReusableView
UICollectionViewCell UICollectionReusableView
UICollectionViewCell UICollectionReusableView
Saturday, April 6, 13 39
40. class hierarchy
NSObject
UIResponder
UIView
UIScrollView
UICollectionView
Saturday, April 6, 13 40
41. 1 Title
Content Content
A 2 Title
Collection Content
View
3 Title
Content Content
Saturday, April 6, 13 41
42. 1 Title
Content Content
2 Title
Sections Content
3 Title
Content Content
Saturday, April 6, 13 42
43. 1 Title
Content Content
2 Title
Cells Content
3 Title
Content Content
Saturday, April 6, 13 43
44. 1 Title
Content Content
Supplementary
2 Title
Views Content
3 Title
Content Content
Saturday, April 6, 13 44
45. Layout
UICollectionViewDataSource
UICollectionView
2
UICollectionViewLayout
UICollectionViewDelegate
UICollectionViewCell UICollectionReusableView
Saturday, April 6, 13 45
46. Custom
layouts
Saturday, April 6, 13 46
47. Layout
Attributes
Saturday, April 6, 13 47
48. Layout Attributes
@interface UICollectionViewLayoutAttributes : NSObject <NSCopying>
@property (nonatomic) CGRect frame;
@property (nonatomic) CGPoint center;
@property (nonatomic) CGSize size;
@property (nonatomic) CATransform3D transform3D;
@property (nonatomic) CGFloat alpha;
@property (nonatomic) NSInteger zIndex;
@property (nonatomic, getter=isHidden) BOOL hidden;
@property (nonatomic, retain) NSIndexPath *indexPath;
@property (nonatomic, readonly) UICollectionElementCategory representedElementCategory;
@property (nonatomic, readonly) NSString *representedElementKind;
+ (instancetype)layoutAttributesForCellWithIndexPath:(NSIndexPath *)indexPath;
+ (instancetype)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind
withIndexPath:(NSIndexPath *)indexPath;
+ (instancetype)layoutAttributesForDecorationViewOfKind:(NSString *)decorationViewKind
withIndexPath:(NSIndexPath*)indexPath;
@end
Saturday, April 6, 13 48
49. Delegate &
Datasource
3
UICollectionViewDataSource
UICollectionView UICollectionViewLayout
UICollectionViewDelegate
UICollectionViewCell UICollectionReusableView
Saturday, April 6, 13 49
50. UI Collection View
UICollectionViewDataSource
UICollectionView UICollectionViewLayout
UICollectionViewDelegate
UICollectionViewCell UICollectionReusableView
UICollectionViewCell UICollectionReusableView
UICollectionViewCell UICollectionReusableView
UICollectionViewCell UICollectionReusableView
Saturday, April 6, 13 50
52. Banner
Parallax
Visible Height
Parallaxing Cell
Components
Banner
Parallaxing Cell
Saturday, April 6, 13 52
53. Banner
One Cell per Section
Parallaxing Cell
Components
Banner
Parallaxing Cell
Saturday, April 6, 13 53
54. rainforest
PXColletionViewController
Custom Layout
UIView UICollectionView PXCollectionViewLayout
PXCollectionViewCell
PXCollectionViewCell UICollectionReusableView
UICollectionReusableView
PXCollectionViewCell
PXCollectionViewCell UICollectionReusableView
PXBannerView
Saturday, April 6, 13 54
55. Px
Collection view
layout
Saturday, April 6, 13 55
57. Px Layout header
static NSString * const kPXBannerSupplementaryViewKind = @"PXBanner";
@protocol PXCollectionViewDelegate <UICollectionViewDelegate>
@optional
- (CGFloat)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
heightForBannerInSection:(NSInteger)section;
@end
...
Saturday, April 6, 13 57
58. Px Layout header
...
@interface PXCollectionViewLayout : UICollectionViewLayout
@property(nonatomic, assign) CGFloat parallaxVisibleHeight;
@end
Saturday, April 6, 13 58
59. A Pattern
1 Author Element View Class
2 Implement DataSource & Delegate
3 Write Layout Algorithm
Saturday, April 6, 13 59
60. Step 1
Banners
Saturday, April 6, 13 60
61. Banner
Parallaxing Cell
Banners
Banner
Parallaxing Cell
Saturday, April 6, 13 61
62. author
Banner view
Saturday, April 6, 13 62
63. rainforest
PXColletionViewController
UIView UICollectionView PXCollectionViewLayout
PXCollectionViewCell UICollectionReusableView
UICollectionReusableView
UICollectionReusableView
PXBannerView
Saturday, April 6, 13 63
65. Banner view
#import <UIKit/UIKit.h>
@interface PXBannerView : UICollectionReusableView
- (void)setImageToImageNamed:(NSString *)imageNamed;
@end
Saturday, April 6, 13 65
66. Banner View
Implementation
Saturday, April 6, 13 66
67. Banner view
#import "PXBannerView.h"
@interface PXBannerView ()
@property(nonatomic, strong) UIImageView *imageView;
@end
@implementation PXBannerView
...
@end
Saturday, April 6, 13 67
68. Banner view
@implementation PXBannerView
...
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.clipsToBounds = YES;
_imageView = [self newImageView];
[self addSubview:_imageView];
}
return self;
}
- (UIImageView *)newImageView {
UIImageView *imageView = [[UIImageView alloc] init];
imageView.contentMode = UIViewContentModeScaleAspectFill;
return imageView;
}
...@end
Saturday, April 6, 13 68
69. Banner view
@implementation PXBannerView
...
- (void)setImageToImageNamed:(NSString *)imageNamed {
UIImage *image = [UIImage imageNamed:imageNamed];
self.imageView.image = image;
}
...
@end
Saturday, April 6, 13 69
70. Banner view
@implementation PXBannerView
...
- (void)layoutSubviews {
[super layoutSubviews];
self.imageView.frame =
CGRectMake(0.0f, 0.0f, self.bounds.size.width, self.bounds.size.height);
}
...
@end
Saturday, April 6, 13 70
71. Banner view
@implementation PXBannerView
...
- (void)prepareForReuse {
[super prepareForReuse];
self.imageView.image = nil;
}
...
@end
Saturday, April 6, 13 71
72. implement the
data source
&
Delegate
Saturday, April 6, 13 72
73. rainforest
PXColletionViewController
UIView UICollectionView PXCollectionViewLayout
PXCollectionViewCell PXBannerView
Saturday, April 6, 13 73
75. We have to create the
collection view.
Saturday, April 6, 13 75
77. VIEW CONTROLLER
#import "PXCollectionViewController.h"
#import "PXCollectionViewLayout.h"
#import "PXBannerView.h"
static NSString * const kPXParallaxCellReuseID = @"PXCellID";
static NSString * const kPXBannerReuseID = @"PXBannerID";
@interface PXCollectionViewController ()<UICollectionViewDataSource,
PXCollectionViewDelegate>
@property(nonatomic, strong) UICollectionView *collectionView;
@end
@implementation PXCollectionViewController
...
@end
Saturday, April 6, 13 77
78. VIEW CONTROLLER
@implementation PXCollectionViewController
- (void)loadView { ... }
- (void)viewDidLoad { ... }
- (void)loadCollectionView { ... }
- (void)viewWillLayoutSubviews { ... }
#pragma mark UICollectionView Datasource
...
#pragma mark PXCollectionView Delegate
...
@end
Saturday, April 6, 13 78
79. 1 Create Collection View
Creation 2 Set Data Source &
Delegate
3 Register Classes
Saturday, April 6, 13 79
80. Create collection view
@implementation PXCollectionViewController
...
- (void)loadCollectionView {
// Create the Collection View.
PXCollectionViewLayout *layout = [[PXCollectionViewLayout alloc] init];
layout.parallaxVisibleHeight = 500.0f;
self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero
collectionViewLayout:layout];
...
}
...
@end
Saturday, April 6, 13 80
81. 1 Create Collection View
Creation 2 Set Data Source &
Delegate
3 Register Classes
Saturday, April 6, 13 81
82. DATASOURCE & DELEGATE
@implementation PXCollectionViewController
...
- (void)loadCollectionView {
...
// Set DataSource and Delegate.
self.collectionView.dataSource = self;
self.collectionView.delegate = self;
...
}
...
@end
Saturday, April 6, 13 82
83. 1 Create Collection View
Creation 2 Set Data Source &
Delegate
3 Register Classes
Saturday, April 6, 13 83
84. Register View classes
@implementation PXCollectionViewController
...
- (void)loadCollectionView {
...
// Register Collection Reusable View Classes.
[self.collectionView registerClass:[UICollectionViewCell class]
forCellWithReuseIdentifier:kPXParallaxCellReuseID];
[self.collectionView registerClass:[PXBannerView class]
forSupplementaryViewOfKind:kPXBannerSupplementaryViewKind
withReuseIdentifier:kPXBannerReuseID];
// Install Collection View into View Hierarchy.
[self.view addSubview:self.collectionView];
}
...
@end
Saturday, April 6, 13 84
87. 1 Number of Sections
Data
Source
2 Number of Items in
Section:
Saturday, April 6, 13 87
88. Data source
@implementation PXCollectionViewController
#pragma mark UICollectionView Datasource
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
return 4;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView
numberOfItemsInSection:(NSInteger)section {
return 1;
}
...
@end
Saturday, April 6, 13 88
89. 1 Cell for Item at Index
Path:
Data
Source
2 View for Supplementary
Element of Kind:
Saturday, April 6, 13 89
90. Data source
@implementation PXCollectionViewController
#pragma mark UICollectionView Datasource
...
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell =
[collectionView dequeueReusableCellWithReuseIdentifier:kPXParallaxCellReuseID
forIndexPath:indexPath];
return cell;
}
...
@end
Saturday, April 6, 13 90
91. Data source
@implementation PXCollectionViewController
#pragma mark UICollectionView Datasource
...
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView
viewForSupplementaryElementOfKind:(NSString *)kind
atIndexPath:(NSIndexPath *)indexPath {
PXBannerView *banner =
[collectionView
dequeueReusableSupplementaryViewOfKind:kPXBannerSupplementaryViewKind
withReuseIdentifier:kPXBannerReuseID
forIndexPath:indexPath];
[banner setImageToImageNamed:[NSString stringWithFormat:@"B%i.jpg",
indexPath.section]];
return banner;
}
@end
Saturday, April 6, 13 91
93. Custom Layout
Collection View Delegate
Saturday, April 6, 13 93
94. Px Layout header
static NSString * const kPXBannerSupplementaryViewKind = @"PXBanner";
@protocol PXCollectionViewDelegate <UICollectionViewDelegate>
@optional
- (CGFloat)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
heightForBannerInSection:(NSInteger)section;
@end
...
Saturday, April 6, 13 94
95. Delegate
@implementation PXCollectionViewController
#pragma mark PXCollectionView Delegate
- (CGFloat)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
heightForBannerInSection:(NSInteger)section {
if (section == 0) {
return 900.0f;
}
return 500.0f;
}
@end
Saturday, April 6, 13 95
98. rainforest
PXColletionViewController
Custom Layout
UIView UICollectionView PXCollectionViewLayout
PXCollectionViewCell PXBannerView
Saturday, April 6, 13 98
99. Layout
implementation
Saturday, April 6, 13 99
100. px Layout
#import "PXCollectionViewLayout.h" Layout Attributes
@interface PXCollectionViewLayout ()
// Layout Metrics.
@property(nonatomic, strong) NSMutableArray *parallaxCellsLayoutAttributes;
@property(nonatomic, strong) NSMutableArray *bannersLayoutAttributes;
@property(nonatomic, assign) CGFloat contentHeight;
@end
@implementation PXCollectionViewLayout
...
@end
Saturday, April 6, 13 100
101. px Layout
@implementation PXCollectionViewLayout
- (void)prepareLayout { ... }
- (void)prepareLayoutForBannerViewInSection:(NSUInteger)section { ... }
- (CGSize)collectionViewContentSize { ... }
...
@end
Saturday, April 6, 13 101
102. px Layout
@implementation PXCollectionViewLayout
...
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { ... }
- (UICollectionViewLayoutAttributes *)
layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { ... }
- (UICollectionViewLayoutAttributes *)
layoutAttributesForSupplementaryViewOfKind:(NSString *)kind
atIndexPath:(NSIndexPath *)indexPath { ... }
...
@end
Saturday, April 6, 13 102
103. px Layout
@implementation PXCollectionViewLayout
...
- (void)clearOutLayoutCalculations { ... }
- (void)setParallaxVisibleHeight:(CGFloat)parallaxVisibleHeight { ... }
@end
Saturday, April 6, 13 103
104. px Layout
@implementation PXCollectionViewLayout
...
- (void)clearOutLayoutCalculations {
self.bannersLayoutAttributes = [NSMutableArray array];
self.parallaxCellsLayoutAttributes = [NSMutableArray array];
self.parallaxingCellIndicies = [NSMutableArray array];
}
- (void)setParallaxVisibleHeight:(CGFloat)parallaxVisibleHeight {
_parallaxVisibleHeight = parallaxVisibleHeight;
[self invalidateLayout];
}
...
@end
Saturday, April 6, 13 104
106. Layout Attributes
@interface UICollectionViewLayoutAttributes : NSObject <NSCopying>
@property (nonatomic) CGRect frame;
@property (nonatomic) CGPoint center;
@property (nonatomic) CGSize size;
@property (nonatomic) CATransform3D transform3D;
@property (nonatomic) CGFloat alpha;
@property (nonatomic) NSInteger zIndex;
@property (nonatomic, getter=isHidden) BOOL hidden;
@property (nonatomic, retain) NSIndexPath *indexPath;
@property (nonatomic, readonly) UICollectionElementCategory representedElementCategory;
@property (nonatomic, readonly) NSString *representedElementKind;
+ (instancetype)layoutAttributesForCellWithIndexPath:(NSIndexPath *)indexPath;
+ (instancetype)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind
withIndexPath:(NSIndexPath *)indexPath;
+ (instancetype)layoutAttributesForDecorationViewOfKind:(NSString *)decorationViewKind
withIndexPath:(NSIndexPath*)indexPath;
@end
Saturday, April 6, 13 106
107. 1 Prepare Layout
Layout
calcs
2 Content Size
Saturday, April 6, 13 107
108. Prepare layout
@implementation PXCollectionViewLayout
...
- (void)prepareLayout {
[super prepareLayout];
// Clear out old layout.
[self clearOutLayoutCalculations];
// Reset content height.
self.contentHeight = 0.0f;
// Get the number of sections from the datasource.
NSUInteger numberOfSections =
[self.collectionView.dataSource numberOfSectionsInCollectionView:self.collectionView];
// Calculate the layout for each banner.
for (int i = 0; i < numberOfSections; i++) {
[self prepareLayoutForBannerViewInSection:i];
}
}
...
@end
Saturday, April 6, 13 108
109. Banner view layout
@implementation PXCollectionViewLayout
...
- (void)prepareLayoutForBannerViewInSection:(NSUInteger)section {
id<PXCollectionViewDelegate> delegate =
(id<PXCollectionViewDelegate>)self.collectionView.delegate;
CGFloat contentWidth = self.collectionView.frame.size.width;
CGFloat bannerHeight = [delegate collectionView:self.collectionView
layout:self
heightForBannerInSection:section];
...
}
...
@end
>
Saturday, April 6, 13 109
110. Banner view layout
@implementation PXCollectionViewLayout
...
- (void)prepareLayoutForBannerViewInSection:(NSUInteger)section {
...
// Banner Layout attributes.
UICollectionViewLayoutAttributes *bannerAttributes =
[UICollectionViewLayoutAttributes
layoutAttributesForSupplementaryViewOfKind:kPXBannerSupplementaryViewKind
withIndexPath:[NSIndexPath
indexPathForItem:0 inSection:section]];
bannerAttributes.frame = CGRectMake(0.0f, self.contentHeight,
contentWidth, bannerHeight);
bannerAttributes.zIndex = 1;
self.bannersLayoutAttributes[section] = bannerAttributes;
self.contentHeight += (bannerHeight + self.parallaxVisibleHeight);
}
...
@end
>
Saturday, April 6, 13 110
111. 1 Prepare Layout
Layout
calcs
2 Content Size
Saturday, April 6, 13 111
112. Layout CONTENT SIZE
@implementation PXCollectionViewLayout
...
- (CGSize)collectionViewContentSize {
return CGSizeMake(self.collectionView.frame.size.width, self.contentHeight);
}
...
@end
Saturday, April 6, 13 112
113. And now the core methods....
Saturday, April 6, 13 113
115. 1 Elements in Rect:
2
LAYOUT
Item at Index Path:
ATTRIBUTES
For:
3 Supplementary View of
Kind: at Index Path:
Saturday, April 6, 13 115
116. 1 Title
Content
Rect Content
Elements 2 Title
in Content
Rect
3 Title
Content Content
Saturday, April 6, 13 116
117. Elements in rect
@implementation PXCollectionViewLayout
...
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
NSMutableArray *layoutAttributesInRect = [NSMutableArray array];
// Banners.
for (UICollectionViewLayoutAttributes *layoutAttributes in
self.bannersLayoutAttributes) {
if (CGRectIntersectsRect(layoutAttributes.frame, rect)) {
[layoutAttributesInRect addObject:layoutAttributes];
}
}
return [layoutAttributesInRect copy];
}
...
@end
Saturday, April 6, 13 117
118. 1 Elements in Rect:
2
LAYOUT
Item at Index Path:
ATTRIBUTES
For:
3 Supplementary View of
Kind: at Index Path:
Saturday, April 6, 13 118
119. at index path
@implementation PXCollectionViewLayout
...
- (UICollectionViewLayoutAttributes *)
layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewLayoutAttributes *layoutAttributes =
[UICollectionViewLayoutAttributes
layoutAttributesForCellWithIndexPath:indexPath];
return layoutAttributes;
}
- (UICollectionViewLayoutAttributes *)
layoutAttributesForSupplementaryViewOfKind:(NSString *)kind
atIndexPath:(NSIndexPath *)indexPath {
UICollectionViewLayoutAttributes *layoutAttributes =
self.bannersLayoutAttributes[indexPath.section];
return layoutAttributes;
}
...
@end
Saturday, April 6, 13 119
121. Step 2
Parallaxing Cells
Saturday, April 6, 13 121
122. Banner
Parallaxing Cell
Components
Banner
Parallaxing Cell
Saturday, April 6, 13 122
123. author
Collection View Cell
Saturday, April 6, 13 123
124. rainforest
PXColletionViewController
UIView UICollectionView PXCollectionViewLayout
PXCollectionViewCell PXBannerView
PXCollectionViewCell
PXCollectionViewCell
PXCollectionViewCell
Saturday, April 6, 13 124
126. 1 Cropped Image
Container View
Cell
2 Collection View Cell
Subclass
Saturday, April 6, 13 126
127. Cropped
Image
Container
Container View
Image View
Saturday, April 6, 13 127
128. Cropped
Image
Container
Reference Frame
Image View
Saturday, April 6, 13 128
129. Cropped
Image
Container
Container View
Image View
Saturday, April 6, 13 129
130. Container View Cropped
Image
Container
Reference Frame
Image View
Saturday, April 6, 13 130
132. Image container View
#import <UIKit/UIKit.h>
@interface PXCroppedImageContainerView : UIView
@property(nonatomic, assign) CGRect referenceFrame;
@property(nonatomic, strong, readonly) UIImageView *imageView;
@property(nonatomic, assign) CGFloat imageViewScale;
- (void)setImageToImageNamed:(NSString *)imageNamed;
@end
Saturday, April 6, 13 132
134. Image container View
@implementation PXCroppedImageContainerView
...
- (void)layoutSubviews {
[super layoutSubviews];
if (CGRectEqualToRect(self.referenceFrame, CGRectZero)) {
return;
}
// Size.
CGSize imageViewSize = [self sizeForImageViewForScale:self.imageViewScale];
self.imageView.frame = CGRectMake(0.0f, 0.0f,
imageViewSize.width, imageViewSize.height);
// Position.
CGPoint imageViewCenter = [self centerPointForImageView];
self.imageView.center = imageViewCenter;
}
...
@end
Saturday, April 6, 13 134
135. Image container View
@implementation PXCroppedImageContainerView
...
- (CGSize)sizeForImageViewForScale:(CGFloat)scale {
CGSize imageViewSize = [self multiplySizeOfRect:self.referenceFrame
byFactor:(scale * 3.0f)];
if (imageViewSize.width < self.referenceFrame.size.width) {
imageViewSize = self.referenceFrame.size;
}
return imageViewSize;
}
- (CGPoint)centerPointForImageView {
return [self centerPointOfRect:self.referenceFrame];
}
...
@end
Saturday, April 6, 13 135
136. 1 Cropped Image
Container View
Cell
2 Collection View Cell
Subclass
Saturday, April 6, 13 136
138. Collection View Cell
#import <UIKit/UIKit.h>
@class PXCroppedImageContainerView;
@interface PXCollectionViewCell : UICollectionViewCell
@property(nonatomic, strong, readonly) PXCroppedImageContainerView *imageContainerView;
- (void)setImageToImageNamed:(NSString *)imageNamed;
@end
Saturday, April 6, 13 138
139. cell
implementation
Saturday, April 6, 13 139
140. Collection View Cell
#import "PXCollectionViewCell.h"
#import "PXCroppedImageContainerView.h"
@interface PXCollectionViewCell ()
@property(nonatomic, strong, readwrite) PXCroppedImageContainerView *imageContainerView;
@end
@implementation PXCollectionViewCell
...
@end
Saturday, April 6, 13 140
141. Collection View Cell
@implementation PXCollectionViewCell
...
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
_imageContainerView = [self newCroppedImageContainerView];
[self.contentView addSubview:_imageContainerView];
}
return self;
}
- (PXCroppedImageContainerView *)newCroppedImageContainerView {
PXCroppedImageContainerView *containerView = [[PXCroppedImageContainerView alloc] init];
return containerView;
}
...
@end
Saturday, April 6, 13 141
142. Collection View Cell
@implementation PXCollectionViewCell
...
- (void)setImageToImageNamed:(NSString *)imageNamed {
[self.imageContainerView setImageToImageNamed:imageNamed];
}
...
@end
Saturday, April 6, 13 142
143. Collection View Cell
@implementation PXCollectionViewCell
...
- (void)prepareForReuse {
[super prepareForReuse];
self.imageContainerView.imageView.image = nil;
}
...
@end
Saturday, April 6, 13 143
144. Collection View Cell
@implementation PXCollectionViewCell
...
#pragma mark Layout
- (void)layoutSubviews {
[super layoutSubviews];
self.imageContainerView.frame = self.contentView.bounds;
}
...
@end
Saturday, April 6, 13 144
147. Register cell class
@implementation PXCollectionViewController
...
- (void)loadCollectionView {
...
[self.collectionView registerClass:[PXCollectionViewCell class]
forCellWithReuseIdentifier:kPXParallaxCellReuseID];
}
...
@end
Saturday, April 6, 13 147
148. implement the
data source
&
Delegate
Saturday, April 6, 13 148
149. rainforest
PXColletionViewController
UIView UICollectionView PXCollectionViewLayout
PXCollectionViewCell PXBannerView
Saturday, April 6, 13 149
150. Cell for index Path
@implementation PXCollectionViewController
...
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath {
// Dequeue cell.
PXCollectionViewCell *cell =
[collectionView dequeueReusableCellWithReuseIdentifier:kPXParallaxCellReuseID
forIndexPath:indexPath];
// Configure cell.
cell.backgroundColor = [UIColor lightGrayColor];
cell.imageContainerView.referenceFrame = CGRectMake(0.0f,
0.0f,
self.collectionView.frame.size.width,
self.collectionView.frame.size.height);
[cell setImageToImageNamed:
[NSString stringWithFormat:@"%i.jpg", indexPath.section]];
return cell;
}
...
@end
Saturday, April 6, 13 150
153. Parallax
Layout
Saturday, April 6, 13 153
154. rainforest
PXColletionViewController
Custom Layout
UIView UICollectionView PXCollectionViewLayout
PXCollectionViewCell PXBannerView
Saturday, April 6, 13 154
155. Banner
Parallaxing Cell
Components
Banner
Parallaxing Cell
Saturday, April 6, 13 155
156. Banner
Parallaxing Cell
Banners
Banner
Parallaxing Cell
Saturday, April 6, 13 156
157. Banner
Cell
Banner
Banner
Banner
Scroll View Contents
Saturday, April 6, 13 157
158. Banner
Cell
Cell 2
Banner
Banner
Banner
Scroll View Contents
Saturday, April 6, 13 158
159. Banner
Cell
Banner Cell 2
Banner
Banner
Scroll View Contents
Saturday, April 6, 13 159
160. Banner
Cell
Banner
Cell 2
Banner
Banner
Scroll View Contents
Saturday, April 6, 13 160
161. Banner
Banner
Cell 2
Banner
Banner
Scroll View Contents
Saturday, April 6, 13 161
162. Banner
Banner
Cell 2
Cell 3
Banner
Banner
Scroll View Contents
Saturday, April 6, 13 162
163. Banner
Banner
Cell 2
Banner
Cell 3
Banner
Scroll View Contents
Saturday, April 6, 13 163
164. Banner
Banner
Cell 2
Banner
Cell 3
Banner
Scroll View Contents
Saturday, April 6, 13 164
165. Banner
Banner
Banner
Cell 3
Banner
Scroll View Contents
Saturday, April 6, 13 165
169. BOUNDS
scroll
View
mechanics
Scroll View Contents
Saturday, April 6, 13 169
170. Anchoring
Subviews
Saturday, April 6, 13 170
171. Subview
BOUNDS
anchoring
subviews
Scroll View Contents
Saturday, April 6, 13 171
172. 1 Anchor
cell
Layout
steps
2 Crop
3 Parallax
Saturday, April 6, 13 172
174. Every time the bounds
changes,
update the subview frame
Saturday, April 6, 13 174
179. -invalidateLayout
Subview -invalidateLayout
-invalidateLayout
-invalidateLayout
-invalidateLayout
BOUNDS
invalidate
layout
Scroll View Contents
Saturday, April 6, 13 179
181. Invalidate layout
will call
prepare layout
and
content size
Saturday, April 6, 13 181
183. Will pick up scroll view
momentum animations
Saturday, April 6, 13 183
186. invalidate layout
@implementation PXCollectionViewLayout
...
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
return YES;
}..
@end
Saturday, April 6, 13 186
187. On invalidate layout
@implementation PXCollectionViewLayout
...
- (void)prepareLayout {
[super prepareLayout];
// Clear out old layout.
[self clearOutLayoutCalculations];
// Reset content height.
self.contentHeight = 0.0f;
// Get the number of sections from the datasource.
NSUInteger numberOfSections =
[self.collectionView.dataSource numberOfSectionsInCollectionView:self.collectionView];
// Calculate the layout for each banner.
for (int i = 0; i < numberOfSections; i++) {
[self prepareLayoutForBannerViewInSection:i];
}
}
...
@end
Saturday, April 6, 13 187
188. Now we can implement
the anchoring layout.
Saturday, April 6, 13 188
189. Anchor
@implementation PXCollectionViewLayout
...
- (void)prepareLayout {
[super prepareLayout];
[self clearOutLayoutCalculations];
self.contentHeight = 0.0f;
NSUInteger numberOfSections =
[self.collectionView.dataSource
numberOfSectionsInCollectionView:self.collectionView];
// Layout for Banners.
for (int i = 0; i < numberOfSections; i++) {
[self prepareLayoutForBannerViewInSection:i];
}
// Layout for Cells. Calculate Each Cell’s Layout
for (int i = 0; i < numberOfSections; i++) {
[self prepareLayoutForParallaxCellInSection:i];
}
} ...
@end
Saturday, April 6, 13 189
190. Anchor
@implementation PXCollectionViewLayout
... Create Layout Attributes
- (void)prepareLayoutForParallaxCellInSection:(NSUInteger)section {
UICollectionViewLayoutAttributes *parallaxCellAttributes =
[UICollectionViewLayoutAttributes
layoutAttributesForCellWithIndexPath:[NSIndexPath indexPathForItem:0
inSection:section]];
[self configureLayoutAttributesForParallaxingCellInSection:section
layoutAttributes:parallaxCellAttributes];
self.parallaxCellsLayoutAttributes[section] = parallaxCellAttributes;
}
...
Store Calculate
@end
Saturday, April 6, 13 190
191. Where the magic happens
@implementation PXCollectionViewLayout
...
- (void)configureLayoutAttributesForParallaxingCellInSection:(NSUInteger)section
layoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes {
// Anchor.
CGFloat bottomOfBounds = CGRectGetMaxY(self.collectionView.bounds);
CGRect newImageFrame =
CGRectMake(0.0f,
(bottomOfBounds - self.collectionView.bounds.size.height),
self.collectionView.bounds.size.width,
self.collectionView.bounds.size.height);
layoutAttributes.frame = newImageFrame;
layoutAttributes.zIndex = -1 * section;
}
...
@end
>
Saturday, April 6, 13 191
194. Banner
Cell 2
Cell
Cell
Banner
Banner
Banner
Scroll View Contents
Saturday, April 6, 13 194
195. Banner
Banner Cell 2
Cell
Cell
Banner
Banner
Scroll View Contents
Saturday, April 6, 13 195
196. Banner
Banner
Cell 2
Cell
Cell
Banner
Banner
Scroll View Contents
Saturday, April 6, 13 196
197. Banner
Banner
Cell 2
Cell
Cell
Banner
Banner
Scroll View Contents
Saturday, April 6, 13 197
198. Banner
Banner
Cell 2
Cell
Cell
Banner
Banner
Scroll View Contents
Saturday, April 6, 13 198
200. Banner
Banner
BOUNDS Determine
Parallaxing
Banner
Cells
Banner
Scroll View Contents
Saturday, April 6, 13 200
202. BUT
There’s no frame.
Saturday, April 6, 13 202
204. Banner
Banner
BOUNDS Determine
Parallaxing
Banner
Cells
Banner
Scroll View Contents
Saturday, April 6, 13 204
205. Banner
BOUNDS
About to
Banner show
Determine
CELL
Parallaxing
Banner
Cells
Banner
Scroll View Contents
Saturday, April 6, 13 205
206. Banner
Banner
Determine
BOUNDS
CELL
Parallaxing
Banner
About to Cells
disappear
Banner
Scroll View Contents
Saturday, April 6, 13 206
207. px Layout
#import "PXCollectionViewLayout.h"
New Property
@interface PXCollectionViewLayout ()
// Layout Metrics.
@property(nonatomic, strong) NSMutableArray *parallaxCellsLayoutAttributes;
@property(nonatomic, strong) NSMutableArray *bannersLayoutAttributes;
@property(nonatomic, assign) CGFloat contentHeight;
@property(nonatomic, strong) NSMutableArray *parallaxingCellIndicies;
@end
@implementation PXCollectionViewLayout
...
@end
Saturday, April 6, 13 207
208. Now we can implement
the logic.
Saturday, April 6, 13 208
209. First, we have to look at the
top of the cell.
Saturday, April 6, 13 209
210. Banner
BOUNDS
About to
Banner show
Determine
CELL
Parallaxing
Banner
Cells
Banner
Scroll View Contents
Saturday, April 6, 13 210
211. Parallaxing indicies
@implementation PXCollectionViewLayout
... New Method
- (void)updateParallaxingCellIndicies {
CGFloat bottomOfBounds = CGRectGetMaxY(self.collectionView.bounds);
CGFloat topOfBounds = CGRectGetMinY(self.collectionView.bounds);
NSMutableArray *parallaxingIndicies = [NSMutableArray array];
// Look for Cells that are Parallaxing or have Parallaxed.
for (int i = 0; i < [self.bannersLayoutAttributes count]; i++) {
UICollectionViewLayoutAttributes *bannerLayoutAttributes =
self.bannersLayoutAttributes[i];
CGFloat bottomOfBanner = CGRectGetMaxY(bannerLayoutAttributes.frame);
if (bottomOfBanner <= bottomOfBounds) {
[parallaxingIndicies addObject:@(i)];
}
}
...
}
...
@end
Saturday, April 6, 13 211
212. Second, we have to look at
the bottom of the cell.
Saturday, April 6, 13 212
213. Banner
Banner
Determine
BOUNDS
CELL
Parallaxing
Banner
About to Cells
disappear
Banner
Scroll View Contents
Saturday, April 6, 13 213
214. Parallaxing indicies
@implementation PXCollectionViewLayout
...
- (void)updateParallaxingCellIndicies {
...
// Remove Cells which are not Parallaxing.
for (int i = 0; i < [self.bannersLayoutAttributes count]; i++) {
UICollectionViewLayoutAttributes *bannerLayoutAttributes =
self.bannersLayoutAttributes[i];
CGFloat topOfBanner = CGRectGetMinY(bannerLayoutAttributes.frame);
if (topOfBanner <= topOfBounds) {
[parallaxingIndicies removeObject:@(i - 1)];
}
}!
self.parallaxingCellIndicies = parallaxingIndicies;
}
...
@end
Saturday, April 6, 13 214
215. Now we have an
array of indices
Saturday, April 6, 13 215
217. Parallaxing indicies
@implementation PXCollectionViewLayout
...
- (BOOL)isParallaxingSection:(NSUInteger)section {
if ([self.parallaxingCellIndicies containsObject:@(section)]) {
return YES;
}
return NO;
}
...
@end
Saturday, April 6, 13 217
218. Last step to anchor,
non parallaxing cells.
Saturday, April 6, 13 218
219. Anchor Parallaxing
Cells
@implementation PXCollectionViewLayout
...
Only Layout Cells on Screen
- (void)prepareLayoutForParallaxCellInSection:(NSUInteger)section {
UICollectionViewLayoutAttributes *parallaxCellAttributes =
[UICollectionViewLayoutAttributes
layoutAttributesForCellWithIndexPath:[NSIndexPath indexPathForItem:0
inSection:section]];
if ([self isParallaxingSection:section]) {
[self configureLayoutAttributesForParallaxingCellInSection:section
layoutAttributes:parallaxCellAttributes];
} else {
parallaxCellAttributes.frame = CGRectZero;
}
self.parallaxCellsLayoutAttributes[section] = parallaxCellAttributes; Calculate
}
...
Store
@end
Saturday, April 6, 13 219
220. We have anchored cells
and only the ones that are
parallaxing are laid out.
Saturday, April 6, 13 220
223. Banner
Cell 2
Cell
Banner
Banner
Banner
Scroll View Contents
Saturday, April 6, 13 223
224. Banner
Banner Cell 2
Cell
Banner
Banner
Scroll View Contents
Saturday, April 6, 13 224
225. Banner
Banner
Cell 2
Cell
Banner
Banner
Scroll View Contents
Saturday, April 6, 13 225
226. Banner
Banner
Cell 2
Banner
Banner
Scroll View Contents
Saturday, April 6, 13 226
227. Banner
Banner
Cell 3
2
Banner
Banner
Scroll View Contents
Saturday, April 6, 13 227
228. Banner
Banner
Banner
Cell 3
2
Banner
Scroll View Contents
Saturday, April 6, 13 228
229. Banner
Banner
Banner
Cell 3
2
Banner
Scroll View Contents
Saturday, April 6, 13 229
230. Banner
Banner
Banner
Cell 3
Banner
Scroll View Contents
Saturday, April 6, 13 230
231. 1 Anchor
cell
Layout
steps
2 Crop
3 Parallax
Saturday, April 6, 13 231
233. z-index
@implementation PXCollectionViewLayout
...
- (void)configureLayoutAttributesForParallaxingCellInSection:(NSUInteger)section
layoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes {
// Anchor.
CGFloat bottomOfBounds = CGRectGetMaxY(self.collectionView.bounds);
CGRect newImageFrame =
CGRectMake(0.0f,
(bottomOfBounds - self.collectionView.bounds.size.height),
self.collectionView.bounds.size.width,
self.collectionView.bounds.size.height);
layoutAttributes.frame = newImageFrame;
layoutAttributes.zIndex = -1 * section;
}
...
@end First One on Top
>
Saturday, April 6, 13 233
234. Banner
Cell
Cell 2
Banner
Banner
Banner
Scroll View Contents
Saturday, April 6, 13 234
235. Banner
Cell
Banner Cell 2
Banner
Banner
Scroll View Contents
Saturday, April 6, 13 235
236. Banner
Cell
Banner
Cell 2
Banner
Banner
Scroll View Contents
Saturday, April 6, 13 236
237. Banner
Banner
Cell 2
Banner
Banner
Scroll View Contents
Saturday, April 6, 13 237
238. Banner
Banner
Cell 2
Cell 3
Banner
Banner
Scroll View Contents
Saturday, April 6, 13 238
239. Banner
Banner
Cell 2
Banner
Cell 3
Banner
Scroll View Contents
Saturday, April 6, 13 239
240. Banner
Banner
Cell 2
Banner
Cell 3
Banner
Scroll View Contents
Saturday, April 6, 13 240
241. Banner
Banner
Banner
Cell 3
Banner
Scroll View Contents
Saturday, April 6, 13 241
243. Banner
Cell
Banner Cell 2
Bottom of Banner
Bottom of Anchor
Banner
Banner
Scroll View Contents
Saturday, April 6, 13 243
244. Crop
@implementation PXCollectionViewLayout
...
- (void)configureLayoutAttributesForParallaxingCellInSection:(NSUInteger)section
layoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes {
// Anchor.
...
// Crop. Test for Crop
// If there's a next banner.
if (section < [self.bannersLayoutAttributes count] - 1) {
UICollectionViewLayoutAttributes *nextCellsBannerLayoutAttributes =
self.bannersLayoutAttributes[section + 1];
CGRect nextBannerFrame = nextCellsBannerLayoutAttributes.frame;
// Crop if necessary.
if (CGRectGetMaxY(newImageFrame) > CGRectGetMaxY(nextBannerFrame)) {
CGFloat amountToCrop =
CGRectGetMaxY(newImageFrame) - CGRectGetMaxY(nextBannerFrame);
newImageFrame.size.height -= amountToCrop;
}
}
Make Cell Shorter
...
}... @end
>
Saturday, April 6, 13 244
246. 1 Anchor
cell
Layout
steps
2 Crop
3 Parallax
Saturday, April 6, 13 246
247. Banner
Cell
Cell 2
Banner
Banner
Banner
Scroll View Contents
Saturday, April 6, 13 247
248. Banner
Cell
Banner Cell 2
Banner
Banner
Scroll View Contents
Saturday, April 6, 13 248
249. Banner
Cell
Banner
Cell 2
Banner
Banner
Scroll View Contents
Saturday, April 6, 13 249
250. Banner
Banner
Cell 2
Banner
Banner
Scroll View Contents
Saturday, April 6, 13 250
251. Banner
Banner
Cell 2
Cell 3
Banner
Banner
Scroll View Contents
Saturday, April 6, 13 251
252. Banner
Banner
Cell 2
Banner
Cell 3
Banner
Scroll View Contents
Saturday, April 6, 13 252
253. Banner
Banner
Cell 2
Banner
Cell 3
Banner
Scroll View Contents
Saturday, April 6, 13 253
254. Banner
Banner
Banner
Cell 3
Banner
Scroll View Contents
Saturday, April 6, 13 254
255. 1 Determine Percentage
2 Define Offset
Parallax
steps
3 Apply Current Offset
Saturday, April 6, 13 255
256. Banner
BOUNDS
Banner
determine
Percentage
0%
Banner
Banner
Scroll View Contents
Saturday, April 6, 13 256
257. Banner
Banner
BOUNDS
determine
Percentage
50%
Banner
Banner
Scroll View Contents
Saturday, April 6, 13 257
258. Banner
Banner
determine
Percentage
100%
Banner
BOUNDS
Banner
Scroll View Contents
Saturday, April 6, 13 258
259. Banner
Current
BOUNDS
Banner Banner
Frame determine
Max Percentage
Banner
Y
Banner
Scroll View Contents
Saturday, April 6, 13 259
260. Banner
BOUNDS
Banner
determine
next
Banner Possible Percentage
Banner
Y
Origin
Banner
Scroll View Contents
Saturday, April 6, 13 260
261. Banner
BOUNDS
Banner
determine
Banner
+
Percentage
Banner
Scroll View Contents
Saturday, April 6, 13 261
262. Banner
Banner
determine
Banner
+
Percentage
BOUNDS
Bounds
Height
Banner
Scroll View Contents
Saturday, April 6, 13 262
263. Banner
Banner
determine
Banner Whole Percentage
BOUNDS
Height
Banner
Scroll View Contents
Saturday, April 6, 13 263
264. Percentage
@implementation PXCollectionViewLayout
...
- (void)configureLayoutAttributesForParallaxingCellInSection:(NSUInteger)section
layoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes {
...
// Parallax.
// Determine Percentage.
UICollectionViewLayoutAttributes *thisCellsBannerLayoutAttributes =
self.bannersLayoutAttributes[section];
CGRect currentBannerFrame = thisCellsBannerLayoutAttributes.frame;
// Get the Whole Height.
CGFloat nextPossibleBannerYOrigin =
CGRectGetMaxY(currentBannerFrame) + self.parallaxVisibleHeight;
...
}... @end
>
Saturday, April 6, 13 264
265. Percentage
@implementation PXCollectionViewLayout
...
- (void)configureLayoutAttributesForParallaxingCellInSection:(NSUInteger)section
layoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes {
...
// Parallax.
// Determine Percentage.
...
Entire Distance
CGFloat parallaxWholeHeight =
(nextPossibleBannerYOrigin + self.collectionView.bounds.size.height);
parallaxWholeHeight -= CGRectGetMaxY(currentBannerFrame);
...
}
...
@end
>
Saturday, April 6, 13 265
266. Banner
Current
BOUNDS
Banner Banner
Frame Starting
Max Point
Banner
Y
Banner
Scroll View Contents
Saturday, April 6, 13 266
267. Percentage
@implementation PXCollectionViewLayout
...
- (void)configureLayoutAttributesForParallaxingCellInSection:(NSUInteger)section
layoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes {
...
// Parallax.
...
Percentage
// Calculate Percentage.
CGFloat percentParallax =
(bottomOfBounds - CGRectGetMaxY(currentBannerFrame)) / parallaxWholeHeight;
...
}... @end
>
Saturday, April 6, 13 267
268. 1 Determine Percentage
2 Define Offset
Parallax
steps
3 Apply Current Offset
Saturday, April 6, 13 268
269. Banner
BOUNDS
Parallaxing Cell
Banner
define
Banner offset
Banner
Scroll View Contents
Saturday, April 6, 13 269
270. BOUNDS
Parallaxing Cell
define
offset
Saturday, April 6, 13 270
271. BOUNDS
Parallaxing Cell
Offset define
offset
0%
Saturday, April 6, 13 271
272. BOUNDS
Parallaxing Cell
Offset define
offset
50%
Saturday, April 6, 13 272
273. BOUNDS
Parallaxing Cell
Offset
define
offset
100%
Saturday, April 6, 13 273
276. Px Layout header
@interface PXCollectionViewLayout : UICollectionViewLayout
@property(nonatomic, assign) CGFloat parallaxVisibleHeight;
@property(nonatomic, assign) CGFloat parallaxOffset;
@end
Saturday, April 6, 13 276
277. Px Layout
@implementation PXCollectionViewLayout
...
- (void)setParallaxOffset:(CGFloat)parallaxOffset {
_parallaxOffset = parallaxOffset;
[self invalidateLayout];
}
...
@end
Saturday, April 6, 13 277
278. Now we can determine the
current offset.
Saturday, April 6, 13 278
279. 0%
+ Offset
Saturday, April 6, 13 279
280. 50%
0 Offset
Saturday, April 6, 13 280
281. 100%
- Offset
Saturday, April 6, 13 281
282. BOUNDS
Parallaxing Cell
Offset
x2
Saturday, April 6, 13 282