UIView转场效果

核心功能如代码所示,其他的请参考附件。

 

 

FlipTransView.h

 

#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>

#define PAGE_VERTICAL_WIDTH                      320.0f
#define PAGE_VERTICAL_HEIGHT                     480.0f
#define PAGE_HORIZONTAL_WIDTH                    480.0f
#define PAGE_HORIZONTAL_HEIGHT                   300.0f

@class FlipTransView;

@protocol FlipTransViewDelegate <NSObject>
@optional
- (void)FlipTransViewDidStart:(FlipTransView *)view;
- (void)FlipTransViewDidFinish:(FlipTransView *)view;
- (void)FlipTransViewDidCancel:(FlipTransView *)view;
@end

typedef enum {
    LTOR = 0,
    RTOL,
} TranDirection;

@interface FlipTransView : UIView {
    id<FlipTransViewDelegate> m_pDelegate;
@private
    CALayer		*m_pTransformed;
    UIView		*m_pSubView;
    UIView		*m_pNewView;
    BOOL		m_bTransitioning;
	BOOL		m_bEnabled;
}

@property (nonatomic, retain) UIView *m_pSubView;
@property (assign) id<FlipTransViewDelegate> m_pDelegate;
@property (readonly, getter = isTransitioning) BOOL m_bTransitioning;

- (void)replaceSubviewInCube:(UIView *)aNewView direction:(TranDirection)aDirection duration:(float)aDuration;
- (void)replaceSubviewInCube:(UIView *)aNewView direction:(TranDirection)aDirection duration:(float)aDuration isMasked:(BOOL)aIsMasked;
@end

 

FlipTransView.m

 

#import "FlipTransView.h"

#define radians(degrees) degrees * M_PI / 180
#define CUBE_VERTICAL_WIDTH PAGE_VERTICAL_WIDTH
#define CUBE_VERTICAL_HEIGHT PAGE_VERTICAL_HEIGHT
#define CUBESIZE 320.0f
#define MASKALPHA 0.4f

#define kAnimationKey @"FlipTransViewAnimation"

@implementation FlipTransView

@synthesize m_pSubView;
@synthesize m_pDelegate;
@synthesize m_bTransitioning;

- (id)initWithFrame:(CGRect)frame {
    if ((self = [super initWithFrame:frame])) {
		m_pSubView = nil;
        m_bTransitioning = NO;
        self.backgroundColor = [UIColor clearColor];
    }
    return self;
}

- (void)addSubview:(UIView *)view {
    if (view != nil) {
        self.m_pSubView = view;
        [super addSubview:view];
    }
}

- (id) captureView:(UIView*)view {
    UIGraphicsBeginImageContext(view.frame.size);
	[view.layer renderInContext:UIGraphicsGetCurrentContext()];
	CGContextSetShouldAntialias(UIGraphicsGetCurrentContext(), true);
	UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
	UIGraphicsEndImageContext();
    
	return (id) [newImage CGImage];
}

- (id) captureView:(UIView *)view isMasked:(BOOL)aIsMasked {
    UIGraphicsBeginImageContext(view.frame.size);
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];
	CGContextSetShouldAntialias(UIGraphicsGetCurrentContext(), true);
    
	if (aIsMasked) {
        CGContextSetRGBFillColor (UIGraphicsGetCurrentContext(), 0, 0, 0, MASKALPHA);
        CGContextFillRect (UIGraphicsGetCurrentContext(), view.frame);
    }
	
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
	UIGraphicsEndImageContext();
    
    return (id) [newImage CGImage];
}

- (CALayer*) makeSurface:(CATransform3D)t withView:(UIView *)aNewView isMasked:(BOOL)aIsMasked {
    CGRect rect = CGRectMake(0, 0, CUBE_VERTICAL_WIDTH, CUBE_VERTICAL_HEIGHT);
    
    CALayer *imageLayer = [CALayer layer];
    imageLayer.anchorPoint = CGPointMake(1, 1);
    imageLayer.frame = rect;
    imageLayer.transform = t; 
    imageLayer.contents = [self captureView:aNewView isMasked:aIsMasked];
    return imageLayer;
}

- (void)constuctRotateLayer:(UIView *)aNewView direction:(TranDirection)aDirection isMasked:(BOOL)aIsMasked {
    //init transformed Layer
    m_pTransformed = [CALayer layer];
    m_pTransformed.frame = self.bounds;
    m_pTransformed.anchorPoint = CGPointMake(0.5f, 0.5f);
    CATransform3D sublayerTransform = CATransform3DIdentity;
	
    /* Set perspective */ 
    sublayerTransform.m34 = 1.0 / -1000;
    [m_pTransformed setSublayerTransform:sublayerTransform];
    
    [self.layer addSublayer:m_pTransformed];
    //init Sublayers
    CATransform3D t = CATransform3DMakeTranslation(0, 0, 0);
	[m_pTransformed addSublayer:[self makeSurface:t withView:m_pSubView isMasked:aIsMasked]];
	[m_pSubView setHidden:YES];

	t = CATransform3DMakeTranslation(0, 0, 0);
	t = CATransform3DTranslate(t, 320, 0, 0);
	t = CATransform3DRotate(t, radians(90), 0, 1, 0);
	CGRect rect = CGRectMake(0, 0, 40, 480);
	CALayer *imageLayer = [CALayer layer];
	imageLayer.anchorPoint = CGPointMake(0, 0);
	imageLayer.frame = rect;
	imageLayer.transform = t; 
	CGImageRef subimage=CGImageCreateWithImageInRect([UIImage imageNamed:@"green_bg_home.png"].CGImage, rect);
	CGContextSetShouldAntialias(UIGraphicsGetCurrentContext(), true);
	imageLayer.contents=(id)subimage;
	CFRelease(subimage);
	[m_pTransformed addSublayer:imageLayer];
	
	t = CATransform3DMakeTranslation(0, 0, 0);
	t = CATransform3DTranslate(t, 0, 0, -40);
	t = CATransform3DRotate(t, radians(180), 0, 1, 0);
	rect = CGRectMake(0, 0, 320, 480);
	imageLayer = [CALayer layer];
	imageLayer.anchorPoint = CGPointMake(0.5, 0.5);
	imageLayer.frame = rect;
	imageLayer.transform = t;  
	imageLayer.contents = [self captureView:aNewView isMasked:aIsMasked];
	[m_pTransformed addSublayer:imageLayer];
}

- (void)destroyRotateLayer {
    [m_pTransformed removeFromSuperlayer];
}

- (void)moveFrom:(TranDirection)aDirection duration:(float)aDuration {
    [CATransaction flush];
    CABasicAnimation *rotation;
    CABasicAnimation *translationX;
    CABasicAnimation *translationZ;
    CAAnimationGroup *group = [CAAnimationGroup animation]; 
    group.delegate = self; 
    group.duration = aDuration; 

	translationX = [CABasicAnimation animationWithKeyPath:@"sublayerTransform.translation.x"];
	translationX.toValue = [NSNumber numberWithFloat:0.0];
	rotation = [CABasicAnimation animationWithKeyPath:@"sublayerTransform.rotation.y"]; 
	rotation.toValue = [NSNumber numberWithFloat:radians(-180)];
	translationZ = [CABasicAnimation animationWithKeyPath:@"sublayerTransform.translation.z"];
	translationZ.toValue = [NSNumber numberWithFloat:0.0];
	
    group.animations = [NSArray arrayWithObjects: rotation, nil];
    group.fillMode = kCAFillModeForwards; 
    group.removedOnCompletion = NO;
    [m_pTransformed addAnimation:group forKey:kAnimationKey];
}

- (void)replaceSubviewInCube:(UIView *)aNewView direction:(TranDirection)aDirection duration:(float)aDuration {
    [self replaceSubviewInCube:aNewView direction:aDirection duration:aDuration isMasked:NO];
}

- (void)replaceSubviewInCube:(UIView *)aNewView direction:(TranDirection)aDirection duration:(float)aDuration isMasked:(BOOL)aIsMasked {
    // If a transition is in progress, do nothing
	if(m_bTransitioning || aNewView == nil)
        return;
    //If there's a new view and it doesn't already have a superview, insert it where the old view was
	if (m_pSubView == nil) {
        [self addSubview:aNewView];
        return;
    }
    
    if ([aNewView superview] != nil) {
        [aNewView removeFromSuperview];
	}
    m_pNewView = aNewView;
	
    [self constuctRotateLayer:aNewView direction:aDirection isMasked:NO];
    [self moveFrom:aDirection duration:aDuration];
}

// Not used in this example, but may be useful in your own project
- (void)cancelTransition {
	// Remove the animation -- cleanup performed in animationDidStop:finished:
	[[self layer] removeAnimationForKey:kAnimationKey];
}

- (void)animationDidStart:(CAAnimation *)animation {
	m_bTransitioning = YES;
    [m_pSubView removeFromSuperview];
    [m_pSubView setHidden:NO];
    // Record the current value of userInteractionEnabled so it can be reset in animationDidStop:finished:
    m_bEnabled = self.userInteractionEnabled;
	
	// If user interaction is not already disabled, disable it for the duration of the animation
	if (m_bEnabled) {
		self.userInteractionEnabled = NO;
    }
    
	// Inform the delegate if the delegate implements the corresponding method
	if(m_pDelegate != nil && [m_pDelegate respondsToSelector:@selector(FlipTransViewDidStart:)]) {
		[m_pDelegate FlipTransViewDidStart:self];
    }
}

- (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)finished {
	m_bTransitioning = NO;
    [self addSubview:m_pNewView];
    [self destroyRotateLayer];
    m_pNewView = nil;
    
	// Reset the original value of userInteractionEnabled
	if (m_bEnabled) {
		self.userInteractionEnabled = YES;
    }
    
	// Inform the delegate if it implements the corresponding method
	if (finished) {
		if (m_pDelegate != nil && [m_pDelegate respondsToSelector:@selector(FlipTransViewDidFinish:)]) {
			[m_pDelegate FlipTransViewDidFinish:self];
        }
	} else {
		if (m_pDelegate != nil && [m_pDelegate respondsToSelector:@selector(FlipTransViewDidCancel:)]) {
			[m_pDelegate FlipTransViewDidCancel:self];
        }
	}
}

- (void)dealloc {
	[m_pSubView release];
    [super dealloc];
}

@end
 

 示例图:


猜你喜欢

转载自eric-gao.iteye.com/blog/1685448