我如何创build在ios垂直翻转视图animation?

我不知道如何垂直翻转我的视图,我有很多意见和我的观点

有一些照片和他们的描述,我想像一本书翻转看,但不是

从左到右必须是从上到下或从下到上,

我想垂直翻转整个页面,如从上到下或从下到上,

如何在iOS中做这种工作?

即时通讯在谷歌上,但多数民众赞成不起作用,我是新的发展

所以,请任何人都可以正确引导我如何翻转我的意见请请帮助我

提前致谢。

https://github.com/mtabini/AFKPageFlipper下载代码

并更改AFKPageFlipper.h和AFKPageFlipper.m文件

// // AFKPageFlipper.h // AFKPageFlipper // // Created by Marco Tabini on 10-10-11. // Copyright 2010 AFK Studio Partnership. All rights reserved. // #import <UIKit/UIKit.h> #import <QuartzCore/QuartzCore.h> @class AFKPageFlipper; @protocol AFKPageFlipperDataSource - (NSInteger) numberOfPagesForPageFlipper:(AFKPageFlipper *) pageFlipper; - (UIView *) viewForPage:(NSInteger) page inFlipper:(AFKPageFlipper *) pageFlipper; @end typedef enum { AFKPageFlipperDirectionTop, AFKPageFlipperDirectionBottom, } AFKPageFlipperDirection; @interface AFKPageFlipper : UIView { NSObject <AFKPageFlipperDataSource> *dataSource; NSInteger currentPage; NSInteger numberOfPages; UIView *currentView; UIView *nextView; CALayer *backgroundAnimationLayer; CALayer *flipAnimationLayer; AFKPageFlipperDirection flipDirection; float startFlipAngle; float endFlipAngle; float currentAngle; BOOL setNextViewOnCompletion; BOOL animating; BOOL disabled; } @property (nonatomic,retain) NSObject <AFKPageFlipperDataSource> *dataSource; @property (nonatomic,assign) NSInteger currentPage; @property (nonatomic, retain) UITapGestureRecognizer *tapRecognizer; @property (nonatomic, retain) UIPanGestureRecognizer *panRecognizer; @property (nonatomic,assign) BOOL disabled; - (void) setCurrentPage:(NSInteger) value animated:(BOOL) animated; @end // // AFKPageFlipper.m // AFKPageFlipper // // Created by Marco Tabini on 10-10-12. // Copyright 2010 AFK Studio Partnership. All rights reserved. // #import "AFKPageFlipper.h" #pragma mark - #pragma mark UIView helpers @interface UIView(Extended) - (UIImage *) imageByRenderingView; @end @implementation UIView(Extended) - (UIImage *) imageByRenderingView { CGFloat oldAlpha = self.alpha; self.alpha = 1; UIGraphicsBeginImageContext(self.bounds.size); [self.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); self.alpha = oldAlpha; return resultingImage; } @end #pragma mark - #pragma mark Private interface @interface AFKPageFlipper() @property (nonatomic,assign) UIView *currentView; @property (nonatomic,assign) UIView *nextView; @end @implementation AFKPageFlipper @synthesize tapRecognizer = _tapRecognizer; @synthesize panRecognizer = _panRecognizer; #pragma mark - #pragma mark Flip functionality - (void) initFlip { // Create screenshots of view UIImage *currentImage = [self.currentView imageByRenderingView]; UIImage *newImage = [self.nextView imageByRenderingView]; // Hide existing views self.currentView.alpha = 0; self.nextView.alpha = 0; // Create representational layers CGRect rect = self.bounds; rect.size.height /= 2; backgroundAnimationLayer = [CALayer layer]; backgroundAnimationLayer.frame = self.bounds; backgroundAnimationLayer.zPosition = -300000; CALayer *topLayer = [CALayer layer]; topLayer.frame = rect; topLayer.masksToBounds = YES; topLayer.contentsGravity = kCAGravityBottom; [backgroundAnimationLayer addSublayer:topLayer]; rect.origin.y = rect.size.height; CALayer *bottomLayer = [CALayer layer]; bottomLayer.frame = rect; bottomLayer.masksToBounds = YES; bottomLayer.contentsGravity = kCAGravityTop; [backgroundAnimationLayer addSublayer:bottomLayer]; if (flipDirection == AFKPageFlipperDirectionBottom) { topLayer.contents = (id) [newImage CGImage]; bottomLayer.contents = (id) [currentImage CGImage]; } else { topLayer.contents = (id) [currentImage CGImage]; bottomLayer.contents = (id) [newImage CGImage]; } [self.layer addSublayer:backgroundAnimationLayer]; rect.origin.y = 0; flipAnimationLayer = [CATransformLayer layer]; flipAnimationLayer.anchorPoint = CGPointMake(0.5, 1); flipAnimationLayer.frame = rect; [self.layer addSublayer:flipAnimationLayer]; CALayer *backLayer = [CALayer layer]; backLayer.frame = flipAnimationLayer.bounds; backLayer.doubleSided = NO; backLayer.masksToBounds = YES; [flipAnimationLayer addSublayer:backLayer]; CALayer *frontLayer = [CALayer layer]; frontLayer.frame = flipAnimationLayer.bounds; frontLayer.doubleSided = NO; frontLayer.masksToBounds = YES; frontLayer.transform = CATransform3DMakeRotation(M_PI, 1.0, 0.0, 0); [flipAnimationLayer addSublayer:frontLayer]; if (flipDirection == AFKPageFlipperDirectionBottom) { backLayer.contents = (id) [currentImage CGImage]; backLayer.contentsGravity = kCAGravityBottom; frontLayer.contents = (id) [newImage CGImage]; frontLayer.contentsGravity = kCAGravityTop; CATransform3D transform = CATransform3DMakeRotation(1.1/M_PI, 1.0, 0.0, 0.0); transform.m34 = 1.0f / 2500.0f; flipAnimationLayer.transform = transform; currentAngle = startFlipAngle = 0; endFlipAngle = M_PI; } else { //down backLayer.contents = (id) [newImage CGImage]; backLayer.contentsGravity = kCAGravityBottom; frontLayer.contents = (id) [currentImage CGImage]; frontLayer.contentsGravity = kCAGravityTop; CATransform3D transform = CATransform3DMakeRotation(M_PI/1.1, 1.0, 0.0, 0.0); transform.m34 = 1.0f / 2500.0f; flipAnimationLayer.transform = transform; currentAngle = startFlipAngle = M_PI; endFlipAngle = 0; } } - (void) cleanupFlip { [backgroundAnimationLayer removeFromSuperlayer]; [flipAnimationLayer removeFromSuperlayer]; backgroundAnimationLayer = Nil; flipAnimationLayer = Nil; animating = NO; if (setNextViewOnCompletion) { [self.currentView removeFromSuperview]; self.currentView = self.nextView; self.nextView = Nil; } else { [self.nextView removeFromSuperview]; self.nextView = Nil; } self.currentView.alpha = 1; } - (void) setFlipProgress:(float) progress setDelegate:(BOOL) setDelegate animate:(BOOL) animate { if (animate) { animating = YES; } 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, 1.0, 0.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) 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]; } #pragma mark - #pragma mark Properties @synthesize currentView; - (void) setCurrentView:(UIView *) value { if (currentView) { [currentView release]; } currentView = [value retain]; } @synthesize nextView; - (void) setNextView:(UIView *) value { if (nextView) { [nextView release]; } nextView = [value retain]; } @synthesize currentPage; - (BOOL) doSetCurrentPage:(NSInteger) value { if (value == currentPage) { return FALSE; } flipDirection = value < currentPage ? AFKPageFlipperDirectionBottom : AFKPageFlipperDirectionTop; currentPage = value; self.nextView = [self.dataSource viewForPage:value inFlipper:self]; [self addSubview:self.nextView]; return TRUE; } - (void) setCurrentPage:(NSInteger) value { if (![self doSetCurrentPage:value]) { return; } setNextViewOnCompletion = YES; animating = YES; self.nextView.alpha = 0; [UIView beginAnimations:@"" context:Nil]; [UIView setAnimationDuration:0.5]; [UIView setAnimationDelegate:self]; [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)]; self.nextView.alpha = 1; [UIView commitAnimations]; } - (void) setCurrentPage:(NSInteger) value animated:(BOOL) animated { if (![self doSetCurrentPage:value]) { return; } setNextViewOnCompletion = YES; animating = YES; if (animated) { [self initFlip]; [self performSelector:@selector(flipPage) withObject:Nil afterDelay:0.091]; } else { [self animationDidStop:Nil finished:[NSNumber numberWithBool:NO] context:Nil]; } } @synthesize dataSource; - (void) setDataSource:(NSObject <AFKPageFlipperDataSource>*) value { if (dataSource) { [dataSource release]; } dataSource = [value retain]; numberOfPages = [dataSource numberOfPagesForPageFlipper:self]; currentPage = 0; self.currentPage = 1; } @synthesize disabled; - (void) setDisabled:(BOOL) value { disabled = value; self.userInteractionEnabled = !value; for (UIGestureRecognizer *recognizer in self.gestureRecognizers) { recognizer.enabled = !value; } } #pragma mark - #pragma mark Touch management - (void) tapped:(UITapGestureRecognizer *) recognizer { if (animating || self.disabled) { return; } if (recognizer.state == UIGestureRecognizerStateRecognized) { NSInteger newPage; if ([recognizer locationInView:self].y < (self.bounds.size.height - self.bounds.origin.y) / 2) { newPage = MAX(1, self.currentPage - 1); } else { newPage = MIN(self.currentPage + 1, numberOfPages); } [self setCurrentPage:newPage animated:YES]; } } - (void) panned:(UIPanGestureRecognizer *) recognizer { if (animating) { return; } static BOOL hasFailed; static BOOL initialized; static NSInteger oldPage; float translation = [recognizer translationInView:self].y; float progress = translation / self.bounds.size.height; if (flipDirection == AFKPageFlipperDirectionTop) { progress = MIN(progress, 0); } else { progress = MAX(progress, 0); } switch (recognizer.state) { case UIGestureRecognizerStateBegan: hasFailed = FALSE; initialized = FALSE; animating = NO; setNextViewOnCompletion = NO; 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; setNextViewOnCompletion = 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 (hasFailed) { [self setFlipProgress:0.0 setDelegate:YES animate:YES]; currentPage = oldPage; return; } if (fabs((translation + [recognizer velocityInView:self].y / 4) / self.bounds.size.height) > 0.5) { setNextViewOnCompletion = YES; [self setFlipProgress:1.0 setDelegate:YES animate:YES]; } else { [self setFlipProgress:0.0 setDelegate:YES animate:YES]; currentPage = oldPage; } break; default: 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 + (Class) layerClass { return [CATransformLayer class]; } - (id)initWithFrame:(CGRect)frame { if ((self = [super initWithFrame:frame])) { _tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapped:)]; _panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panned:)]; [_tapRecognizer requireGestureRecognizerToFail:_panRecognizer]; [self addGestureRecognizer:_tapRecognizer]; [self addGestureRecognizer:_panRecognizer]; } return self; } - (void)dealloc { self.dataSource = Nil; self.currentView = Nil; self.nextView = Nil; self.tapRecognizer = Nil; self.panRecognizer = Nil; [super dealloc]; } @end 

因为AFKPageFlipper,我能够做到上面的代码….信贷去先生mtabini(AFKPageFlipper作者)

你可以设置一个负值,比如:

 [theView setTransform:CGAffineTransformMakeScale(1, -1)]; 

和Pradeep一样,但是有了阴影,ARC也改编了:

AFKPageFlipper.h

 // // AFKPageFlipper.h // AFKPageFlipper // // Created by Marco Tabini on 10-10-11. // Copyright 2010 AFK Studio Partnership. All rights reserved. // #import <UIKit/UIKit.h> #import <QuartzCore/QuartzCore.h> @class AFKPageFlipper; @protocol AFKPageFlipperDataSource - (NSInteger) numberOfPagesForPageFlipper:(AFKPageFlipper *) pageFlipper; - (UIView *) viewForPage:(NSInteger) page inFlipper:(AFKPageFlipper *) pageFlipper; @end typedef enum { AFKPageFlipperDirectionTop, AFKPageFlipperDirectionBottom, } AFKPageFlipperDirection; @interface AFKPageFlipper : UIView { NSObject <AFKPageFlipperDataSource> *dataSource; NSInteger currentPage; NSInteger numberOfPages; // shadows CALayer *frontLayerShadow; CALayer *backLayerShadow; CALayer *leftLayerShadow; CALayer *rightLayerShadow; // shadows CALayer *backgroundAnimationLayer; CALayer *flipAnimationLayer; AFKPageFlipperDirection flipDirection; float startFlipAngle; float endFlipAngle; float currentAngle; BOOL setNextViewOnCompletion; BOOL animating; BOOL disabled; } @property (nonatomic,retain) NSObject <AFKPageFlipperDataSource> *dataSource; @property (nonatomic,assign) NSInteger currentPage; @property (nonatomic, retain) UITapGestureRecognizer *tapRecognizer; @property (nonatomic, retain) UIPanGestureRecognizer *panRecognizer; @property (nonatomic,assign) BOOL disabled; - (void) setCurrentPage:(NSInteger) value animated:(BOOL) animated; @end 

AFKPageFlipper.m

 // // AFKPageFlipper.m // AFKPageFlipper // // Created by Marco Tabini on 10-10-12. // Copyright 2010 AFK Studio Partnership. All rights reserved. // #import "AFKPageFlipper.h" #pragma mark - #pragma mark UIView helpers @interface UIView(Extended) - (UIImage *) imageByRenderingView; @end @implementation UIView(Extended) - (UIImage *) imageByRenderingView { CGFloat oldAlpha = self.alpha; self.alpha = 1; UIGraphicsBeginImageContext(self.bounds.size); [self.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); self.alpha = oldAlpha; return resultingImage; } @end #pragma mark - #pragma mark Private interface @interface AFKPageFlipper() @property (nonatomic,retain) UIView *currentView; @property (nonatomic,retain) UIView *nextView; @end @implementation AFKPageFlipper @synthesize tapRecognizer = _tapRecognizer; @synthesize panRecognizer = _panRecognizer; #pragma mark - #pragma mark Flip functionality - (void) initFlip { // Create screenshots of view UIImage *currentImage = [self.currentView imageByRenderingView]; UIImage *newImage = [self.nextView imageByRenderingView]; // Hide existing views self.currentView.alpha = 0; self.nextView.alpha = 0; // Create representational layers CGRect rect = self.bounds; rect.size.height /= 2; backgroundAnimationLayer = [CALayer layer]; backgroundAnimationLayer.frame = self.bounds; backgroundAnimationLayer.zPosition = -300000; CALayer *topLayer = [CALayer layer]; topLayer.frame = rect; topLayer.masksToBounds = YES; topLayer.contentsGravity = kCAGravityBottom; [backgroundAnimationLayer addSublayer:topLayer]; rect.origin.y = rect.size.height; CALayer *bottomLayer = [CALayer layer]; bottomLayer.frame = rect; bottomLayer.masksToBounds = YES; bottomLayer.contentsGravity = kCAGravityTop; [backgroundAnimationLayer addSublayer:bottomLayer]; if (flipDirection == AFKPageFlipperDirectionBottom) { topLayer.contents = (id) [newImage CGImage]; bottomLayer.contents = (id) [currentImage CGImage]; } else { topLayer.contents = (id) [currentImage CGImage]; bottomLayer.contents = (id) [newImage CGImage]; } [self.layer addSublayer:backgroundAnimationLayer]; rect.origin.y = 0; flipAnimationLayer = [CATransformLayer layer]; flipAnimationLayer.anchorPoint = CGPointMake(0.5, 1); flipAnimationLayer.frame = rect; [self.layer addSublayer:flipAnimationLayer]; CALayer *backLayer = [CALayer layer]; backLayer.frame = flipAnimationLayer.bounds; backLayer.doubleSided = NO; backLayer.masksToBounds = YES; [flipAnimationLayer addSublayer:backLayer]; CALayer *frontLayer = [CALayer layer]; frontLayer.frame = flipAnimationLayer.bounds; frontLayer.doubleSided = NO; frontLayer.masksToBounds = YES; frontLayer.transform = CATransform3DMakeRotation(M_PI, 1.0, 0, 0); [flipAnimationLayer addSublayer:frontLayer]; // shadows frontLayerShadow = [CALayer layer]; frontLayerShadow.frame = frontLayer.bounds; frontLayerShadow.doubleSided = NO; frontLayerShadow.masksToBounds = YES; frontLayerShadow.opacity = 0; frontLayerShadow.backgroundColor = [UIColor blackColor].CGColor; [frontLayer addSublayer:frontLayerShadow]; backLayerShadow = [CALayer layer]; backLayerShadow.frame = backLayer.bounds; backLayerShadow.doubleSided = NO; backLayerShadow.masksToBounds = YES; backLayerShadow.opacity = 0; backLayerShadow.backgroundColor = [UIColor blackColor].CGColor; [backLayer addSublayer:backLayerShadow]; leftLayerShadow = [CALayer layer]; leftLayerShadow.frame = topLayer.bounds; leftLayerShadow.doubleSided = NO; leftLayerShadow.masksToBounds = YES; leftLayerShadow.opacity = 0.0; leftLayerShadow.backgroundColor = [UIColor blackColor].CGColor; [topLayer addSublayer:leftLayerShadow]; rightLayerShadow = [CALayer layer]; rightLayerShadow.frame = bottomLayer.bounds; rightLayerShadow.doubleSided = NO; rightLayerShadow.masksToBounds = YES; rightLayerShadow.opacity = 0.0; rightLayerShadow.backgroundColor = [UIColor blackColor].CGColor; [bottomLayer addSublayer:rightLayerShadow]; // shadows if (flipDirection == AFKPageFlipperDirectionBottom) { backLayer.contents = (id) [currentImage CGImage]; backLayer.contentsGravity = kCAGravityBottom; frontLayer.contents = (id) [newImage CGImage]; frontLayer.contentsGravity = kCAGravityTop; CATransform3D transform = CATransform3DMakeRotation(1.1/M_PI, 1.0, 0.0, 0.0); transform.m34 = 1.0f / 2500.0f; flipAnimationLayer.transform = transform; currentAngle = startFlipAngle = 0; endFlipAngle = M_PI; } else { //down backLayer.contents = (id) [newImage CGImage]; backLayer.contentsGravity = kCAGravityBottom; frontLayer.contents = (id) [currentImage CGImage]; frontLayer.contentsGravity = kCAGravityTop; CATransform3D transform = CATransform3DMakeRotation(M_PI/1.1, 1.0, 0.0, 0.0); transform.m34 = 1.0f / 2500.0f; flipAnimationLayer.transform = transform; currentAngle = startFlipAngle = M_PI; endFlipAngle = 0; } } - (void) cleanupFlip { [backgroundAnimationLayer removeFromSuperlayer]; [flipAnimationLayer removeFromSuperlayer]; backgroundAnimationLayer = Nil; flipAnimationLayer = Nil; animating = NO; if (setNextViewOnCompletion) { [self.currentView removeFromSuperview]; self.currentView = self.nextView; self.nextView = Nil; } else { [self.nextView removeFromSuperview]; self.nextView = Nil; } self.currentView.alpha = 1; } - (void) setFlipProgress:(float) progress setDelegate:(BOOL) setDelegate animate:(BOOL) animate { if (animate) { animating = YES; } 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, 1.0, 0.0, 0.0); [flipAnimationLayer removeAllAnimations]; // shadows //NSLog(@"End flip angle: %.0f, \tstartflip: %.0f, \tprogress: %.2f\tduration: %.2f", endFlipAngle, startFlipAngle,progress, duration); CGFloat newShadowOpacity = (0.5 - progress); if(newShadowOpacity < 0) { newShadowOpacity *= -1; } if (newShadowOpacity < 0.05) { newShadowOpacity = 0; } // shadows if (duration < 0.15) { duration = 0.15; } [UIView animateWithDuration: duration delay: 0 options: UIViewAnimationOptionCurveLinear animations: ^(void) { flipAnimationLayer.transform = endTransform; if (endFlipAngle < startFlipAngle) { if(progress < 0.5) { rightLayerShadow.opacity = newShadowOpacity; frontLayerShadow.opacity = (0.5 - newShadowOpacity)/2; } else { backLayerShadow.opacity = (0.5 - newShadowOpacity)/2; leftLayerShadow.opacity = newShadowOpacity; } } else { if(progress < 0.5) { leftLayerShadow.opacity = newShadowOpacity; backLayerShadow.opacity = (0.5 - newShadowOpacity)/2; } else { frontLayerShadow.opacity = (0.5 - newShadowOpacity)/2; rightLayerShadow.opacity = newShadowOpacity; } } // shadows } completion: ^(BOOL completion) { }]; if (setDelegate) { [self performSelector:@selector(cleanupFlip) withObject:Nil afterDelay:duration]; } } - (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]; } #pragma mark - #pragma mark Properties @synthesize currentPage; - (BOOL) doSetCurrentPage:(NSInteger) value { if (value == currentPage) { return FALSE; } flipDirection = value < currentPage ? AFKPageFlipperDirectionBottom : AFKPageFlipperDirectionTop; currentPage = value; self.nextView = [self.dataSource viewForPage:value inFlipper:self]; [self addSubview:self.nextView]; return TRUE; } - (void) setCurrentPage:(NSInteger) value { if (![self doSetCurrentPage:value]) { return; } setNextViewOnCompletion = YES; animating = YES; self.nextView.alpha = 0; [UIView beginAnimations:@"" context:Nil]; [UIView setAnimationDuration:0.5]; [UIView setAnimationDelegate:self]; [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)]; self.nextView.alpha = 1; [UIView commitAnimations]; } - (void) setCurrentPage:(NSInteger) value animated:(BOOL) animated { if (![self doSetCurrentPage:value]) { return; } setNextViewOnCompletion = YES; animating = YES; if (animated) { [self initFlip]; [self performSelector:@selector(flipPage) withObject:Nil afterDelay:0.091]; } else { [self animationDidStop:Nil finished:[NSNumber numberWithBool:NO] context:Nil]; } } @synthesize dataSource; - (void) setDataSource:(NSObject <AFKPageFlipperDataSource>*) value { if (dataSource) { dataSource = nil; } dataSource = value; numberOfPages = [dataSource numberOfPagesForPageFlipper:self]; currentPage = 0; self.currentPage = 1; } @synthesize disabled; - (void) setDisabled:(BOOL) value { disabled = value; self.userInteractionEnabled = !value; for (UIGestureRecognizer *recognizer in self.gestureRecognizers) { recognizer.enabled = !value; } } #pragma mark - #pragma mark Touch management - (void) tapped:(UITapGestureRecognizer *) recognizer { if (animating || self.disabled) { return; } if (recognizer.state == UIGestureRecognizerStateRecognized) { NSInteger newPage; if ([recognizer locationInView:self].y < (self.bounds.size.height - self.bounds.origin.y) / 2) { newPage = MAX(1, self.currentPage - 1); } else { newPage = MIN(self.currentPage + 1, numberOfPages); } [self setCurrentPage:newPage animated:YES]; } } - (void) panned:(UIPanGestureRecognizer *) recognizer { if (animating) { return; } static BOOL hasFailed; static BOOL initialized; static NSInteger oldPage; float translation = [recognizer translationInView:self].y; float progress = translation / self.bounds.size.height; if (flipDirection == AFKPageFlipperDirectionTop) { progress = MIN(progress, 0); } else { progress = MAX(progress, 0); } switch (recognizer.state) { case UIGestureRecognizerStateBegan: hasFailed = FALSE; initialized = FALSE; animating = NO; setNextViewOnCompletion = NO; 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; setNextViewOnCompletion = 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 (hasFailed) { [self setFlipProgress:0.0 setDelegate:YES animate:YES]; currentPage = oldPage; return; } if (fabs((translation + [recognizer velocityInView:self].y / 4) / self.bounds.size.height) > 0.5) { setNextViewOnCompletion = YES; [self setFlipProgress:1.0 setDelegate:YES animate:YES]; } else { [self setFlipProgress:0.0 setDelegate:YES animate:YES]; currentPage = oldPage; } break; default: 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 + (Class) layerClass { return [CATransformLayer class]; } - (id)initWithFrame:(CGRect)frame { if ((self = [super initWithFrame:frame])) { [self initRecognizers]; } return self; } - (id)initWithCoder:(NSCoder *)aDecoder { if ((self = [super initWithCoder: aDecoder])) { [self initRecognizers]; } return self; } - (void) initRecognizers { _tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapped:)]; _panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panned:)]; [_tapRecognizer requireGestureRecognizerToFail:_panRecognizer]; [self addGestureRecognizer:_tapRecognizer]; [self addGestureRecognizer:_panRecognizer]; } @end