我不知道如何垂直翻转我的uiview,我有很多视图,我每个视图
有一些照片和他们的描述,我想要一个像书一样的翻转视图,但不是
从左到右必须是从上到下或从下到上,
我想垂直翻转整个页面,如从上到下或从下到上,
如何在 ios 中做这种工作?
我在谷歌上搜索,但那不起作用我是开发新手
所以请任何人都可以正确指导我如何翻转我的观点请帮助我
出去
提前致谢。
我不知道如何垂直翻转我的uiview,我有很多视图,我每个视图
有一些照片和他们的描述,我想要一个像书一样的翻转视图,但不是
从左到右必须是从上到下或从下到上,
我想垂直翻转整个页面,如从上到下或从下到上,
如何在 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