Comment puis-je créer une animation Flip View verticale dans ios?

Je ne sais pas comment returnner mon uiview verticalement, j'ai beaucoup de vues et je chaque vue

il y a quelques photos et leur description, je veux une vue flip comme un livre mais pas

de gauche à droite, il doit être de haut en bas ou de bas en haut,

je veux returnner la page entière verticalement comme de haut en bas ou de bas en haut,

comment faire ce genre de travail dans ios?

im seraching sur google mais ça ne marche pas je suis nouveau dans le développement

Alors, s'il vous plaît, n'importe qui peut me guider correctement, comment puis-je returnner mes vues S'il vous plaît, s'il vous plaît aidez-moi

en dehors

Merci d'avance.

téléchargez le code depuis https://github.com/mtabini/AFKPageFlipper

et modifiez le file AFKPageFlipper.h et 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:(NSSsortingng *) 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 

becoz de AFKPageFlipper, je suis capable de faire le code ci-dessus …. crédit va à M. mtabini (auteur AFKPageFlipper)

Vous pouvez définir une échelle négative, comme:

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

Même que Pradeep, mais avec des ombres, aussi ARC adapté:

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:(NSSsortingng *) 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