Skip to content

Commit

Permalink
- Working flipper
Browse files Browse the repository at this point in the history
  • Loading branch information
mtabini committed Oct 15, 2010
1 parent f3b8fd4 commit 8d68ed3
Show file tree
Hide file tree
Showing 6 changed files with 6,105 additions and 180 deletions.
6,048 changes: 5,911 additions & 137 deletions AFKPageFlipper.xcodeproj/marcot.pbxuser

Large diffs are not rendered by default.

28 changes: 13 additions & 15 deletions AFKPageFlipper.xcodeproj/marcot.perspectivev3
Expand Up @@ -274,14 +274,12 @@
<string>29B97315FDCFA39411CA2CEA</string>
<string>29B97317FDCFA39411CA2CEA</string>
<string>29B97323FDCFA39411CA2CEA</string>
<string>1C77FABC04509CD000000102</string>
</array>
<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
<array>
<array>
<integer>7</integer>
<integer>5</integer>
<integer>1</integer>
<integer>0</integer>
<integer>33</integer>
</array>
</array>
<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
Expand Down Expand Up @@ -320,31 +318,31 @@
<key>PBXProjectModuleGUID</key>
<string>8FBAC1921263F96A00881579</string>
<key>PBXProjectModuleLabel</key>
<string>MainController.m</string>
<string>AFKPageFlipper.m</string>
<key>PBXSplitModuleInNavigatorKey</key>
<dict>
<key>Split0</key>
<dict>
<key>PBXProjectModuleGUID</key>
<string>8FBAC1931263F96A00881579</string>
<key>PBXProjectModuleLabel</key>
<string>MainController.m</string>
<string>AFKPageFlipper.m</string>
<key>_historyCapacity</key>
<integer>0</integer>
<key>bookmark</key>
<string>8FAEF4461266C73900D88B84</string>
<string>8FAEF9B01267F13000D88B84</string>
<key>history</key>
<array>
<string>8FBAC1B61263FAD100881579</string>
<string>8FBAC1D81263FB4000881579</string>
<string>8FBAC1E01263FBC800881579</string>
<string>8FBAC89A1264375000881579</string>
<string>8FAEF24F1266B43E00D88B84</string>
<string>8FAEF3451266BE7900D88B84</string>
<string>8FAEF3E91266C4C400D88B84</string>
<string>8FAEF42E1266C67E00D88B84</string>
<string>8FAEF4441266C73900D88B84</string>
<string>8FAEF4451266C73900D88B84</string>
<string>8FAEF47D1266CA2400D88B84</string>
<string>8FAEF47E1266CA2400D88B84</string>
<string>8FAEF9671267E1E700D88B84</string>
<string>8FAEF9A61267E95900D88B84</string>
</array>
</dict>
<key>SplitCount</key>
Expand Down Expand Up @@ -384,8 +382,6 @@
<dict>
<key>Frame</key>
<string>{{10, 27}, {1713, -27}}</string>
<key>RubberWindowFrame</key>
<string>0 59 1920 1119 0 0 1920 1178 </string>
</dict>
<key>Module</key>
<string>XCDetailModule</string>
Expand All @@ -401,7 +397,9 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
<string>{{10, 31}, {603, 297}}</string>
<string>{{10, 27}, {1713, -27}}</string>
<key>RubberWindowFrame</key>
<string>0 59 1920 1119 0 0 1920 1178 </string>
</dict>
<key>Module</key>
<string>PBXProjectFindModule</string>
Expand Down Expand Up @@ -662,7 +660,7 @@
<integer>5</integer>
<key>WindowOrderList</key>
<array>
<string>8FAEF4471266C73900D88B84</string>
<string>8FAEF9B11267F13000D88B84</string>
<string>8FAEF3CC1266C32100D88B84</string>
<string>8FAEF1951266AF5F00D88B84</string>
<string>8FAEF1961266AF5F00D88B84</string>
Expand Down
3 changes: 3 additions & 0 deletions Classes/AFKPageFlipper.h
Expand Up @@ -31,6 +31,7 @@ typedef enum {
@interface AFKPageFlipper : UIView {
NSObject <AFKPageFlipperDataSource> *dataSource;
NSInteger currentPage;
NSInteger numberOfPages;

UIView *currentView;
UIView *newView;
Expand All @@ -41,8 +42,10 @@ typedef enum {
AFKPageFlipperDirection flipDirection;
float startFlipAngle;
float endFlipAngle;
float currentAngle;

BOOL setNewViewOnCompletion;
BOOL animating;
}

@property (nonatomic,retain) NSObject <AFKPageFlipperDataSource> *dataSource;
Expand Down
204 changes: 177 additions & 27 deletions Classes/AFKPageFlipper.m
Expand Up @@ -132,28 +132,26 @@ - (void) initFlip {
frontLayer.contents = (id) [newImage CGImage];
frontLayer.contentsGravity = kCAGravityRight;

CATransform3D transform = CATransform3DIdentity;
CATransform3D transform = CATransform3DMakeRotation(0.0, 0.0, 1.0, 0.0);
transform.m34 = 1.0f / 2500.0f;
transform = CATransform3DRotate(transform, -M_PI, 0.0, 1.0, 0.0);

flipAnimationLayer.transform = transform;

startFlipAngle = 0;
startFlipAngle = -M_PI;
currentAngle = startFlipAngle = 0;
endFlipAngle = -M_PI;
} else {
backLayer.contentsGravity = kCAGravityLeft;
backLayer.contents = (id) [newImage CGImage];

frontLayer.contents = (id) [currentImage CGImage];
frontLayer.contentsGravity = kCAGravityRight;

CATransform3D transform = CATransform3DIdentity;
CATransform3D transform = CATransform3DMakeRotation(-M_PI / 1.1, 0.0, 1.0, 0.0);
transform.m34 = 1.0f / 2500.0f;
transform = CATransform3DRotate(transform, 0, 0.0, 1.0, 0.0);

flipAnimationLayer.transform = transform;

startFlipAngle = -M_PI;
currentAngle = startFlipAngle = -M_PI;
endFlipAngle = 0;
}
}
Expand All @@ -166,28 +164,56 @@ - (void) cleanupFlip {
backgroundAnimationLayer = Nil;
flipAnimationLayer = Nil;

animating = NO;

if (setNewViewOnCompletion) {
[self.currentView removeFromSuperview];
self.currentView = self.newView;
self.newView = Nil;

self.currentView.alpha = 1;
} else {
[self.newView removeFromSuperview];
self.newView = Nil;
}

self.currentView.alpha = 1;
}

#pragma mark -
#pragma mark Animation management

- (void) setFlipProgress:(float) progress setDelegate:(BOOL) setDelegate animate:(BOOL) animate {
float newAngle = startFlipAngle + progress * (endFlipAngle - startFlipAngle);

float duration = animate ? 0.5 * fabs((newAngle - currentAngle) / (endFlipAngle - startFlipAngle)) : 0;

currentAngle = newAngle;

CATransform3D endTransform = CATransform3DIdentity;
endTransform.m34 = 1.0f / 2500.0f;
endTransform = CATransform3DRotate(endTransform, newAngle, 0.0, 1.0, 0.0);

[flipAnimationLayer removeAllAnimations];

[CATransaction begin];
[CATransaction setAnimationDuration:duration];

flipAnimationLayer.transform = endTransform;

[CATransaction commit];

if (setDelegate) {
[self performSelector:@selector(cleanupFlip) withObject:Nil afterDelay:duration];
}
}


- (void)animationDidStop:(CAAnimation *) theAnimation finished:(BOOL) flag {
[self cleanupFlip];
- (void) flipPage {
[self setFlipProgress:1.0 setDelegate:YES animate:YES];
}


#pragma mark -
#pragma mark Animation management


- (void)animationDidStop:(NSString *) animationID finished:(NSNumber *) finished context:(void *) context {
[self cleanupFlip];
}
Expand Down Expand Up @@ -228,7 +254,8 @@ - (BOOL) doSetCurrentPage:(NSInteger) value {
return FALSE;
}

flipDirection = (value < currentPage ? AFKPageFlipperDirectionRight : AFKPageFlipperDirectionLeft);
flipDirection = value < currentPage ? AFKPageFlipperDirectionRight : AFKPageFlipperDirectionLeft;

currentPage = value;

self.newView = [self.dataSource viewForPage:value inFlipper:self];
Expand All @@ -243,6 +270,8 @@ - (void) setCurrentPage:(NSInteger) value {
}

setNewViewOnCompletion = YES;
animating = YES;

self.newView.alpha = 0;

[UIView beginAnimations:@"" context:Nil];
Expand All @@ -262,21 +291,16 @@ - (void) setCurrentPage:(NSInteger) value animated:(BOOL) animated {
return;
}

if ([self doSetCurrentPage:value]) {
[self initFlip];
if (![self doSetCurrentPage:value]) {
return;
}

setNewViewOnCompletion = YES;

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];

animation.duration = 1.0;
animation.fromValue = [NSNumber numberWithFloat:startFlipAngle];
animation.toValue = [NSNumber numberWithFloat:endFlipAngle];
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.delegate = self;
[self initFlip];

[flipAnimationLayer addAnimation:animation forKey:Nil];
setNewViewOnCompletion = YES;
animating = YES;

[self performSelector:@selector(flipPage) withObject:Nil afterDelay:0.001];
}


Expand All @@ -289,10 +313,130 @@ - (void) setDataSource:(NSObject <AFKPageFlipperDataSource>*) value {
}

dataSource = [value retain];
numberOfPages = [dataSource numberOfPagesForPageFlipper:self];
self.currentPage = 1;
}


#pragma mark -
#pragma mark Touch management


- (void) tapped:(UITapGestureRecognizer *) recognizer {
if (animating) {
return;
}

if (recognizer.state == UIGestureRecognizerStateRecognized) {
NSInteger newPage;

if ([recognizer locationInView:self].x < (self.bounds.size.width - self.bounds.origin.x) / 2) {
newPage = MAX(1, self.currentPage - 1);
} else {
newPage = MIN(self.currentPage + 1, numberOfPages);
}

[self setCurrentPage:newPage animated:YES];
}
}


- (void) panned:(UIPanGestureRecognizer *) recognizer {
static BOOL hasFailed;
static BOOL initialized;

static NSInteger oldPage;

float translation = [recognizer translationInView:self].x;

float progress = translation / self.bounds.size.width;

if (flipDirection == AFKPageFlipperDirectionLeft) {
progress = MIN(progress, 0);
} else {
progress = MAX(progress, 0);
}

switch (recognizer.state) {
case UIGestureRecognizerStateBegan:
hasFailed = FALSE;
initialized = FALSE;
break;


case UIGestureRecognizerStateChanged:

if (hasFailed) {
return;
}

if (!initialized) {
oldPage = self.currentPage;

if (translation > 0) {
if (self.currentPage > 1) {
[self doSetCurrentPage:self.currentPage - 1];
} else {
hasFailed = TRUE;
return;
}
} else {
if (self.currentPage < numberOfPages) {
[self doSetCurrentPage:self.currentPage + 1];
} else {
hasFailed = TRUE;
return;
}
}

hasFailed = NO;
initialized = TRUE;
animating = YES;
setNewViewOnCompletion = NO;

[self initFlip];
}

[self setFlipProgress:fabs(progress) setDelegate:NO animate:NO];

break;


case UIGestureRecognizerStateFailed:
[self setFlipProgress:0.0 setDelegate:YES animate:YES];
currentPage = oldPage;
break;

case UIGestureRecognizerStateRecognized:
if (fabs((translation + [recognizer velocityInView:self].x / 4) / self.bounds.size.width) > 0.5) {
setNewViewOnCompletion = YES;
[self setFlipProgress:1.0 setDelegate:YES animate:YES];
} else {
[self setFlipProgress:0.0 setDelegate:YES animate:YES];
currentPage = oldPage;
}

break;
}
}


#pragma mark -
#pragma mark Frame management


- (void) setFrame:(CGRect) value {
super.frame = value;

numberOfPages = [dataSource numberOfPagesForPageFlipper:self];

if (self.currentPage > numberOfPages) {
self.currentPage = numberOfPages;
}

}


#pragma mark -
#pragma mark Initialization and memory management

Expand All @@ -304,7 +448,13 @@ + (Class) layerClass {

- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
// Initialization code
UITapGestureRecognizer *tapRecognizer = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapped:)] autorelease];
UIPanGestureRecognizer *panRecognizer = [[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panned:)] autorelease];

[tapRecognizer requireGestureRecognizerToFail:panRecognizer];

[self addGestureRecognizer:tapRecognizer];
[self addGestureRecognizer:panRecognizer];
}
return self;
}
Expand Down

0 comments on commit 8d68ed3

Please sign in to comment.