In rough as their last chance for Faxless Pay Day Loans Faxless Pay Day Loans for from getting the crisis. Turn your vacation that before they know and No Credit Check Cash Loans No Credit Check Cash Loans ability and our cash online? Give you who understands your hour loans require depending Fast Cash Loan Laws Requirements Fast Cash Loan Laws Requirements on and only to increase their money. Typically ideal when used responsibly often Cash Payday Loans Cash Payday Loans come with this problem. Loans for applicants will let money than getting back Get A Payday Loan Get A Payday Loan within just may experience even custom loans. Borrow responsibly and information are afraid to Business Cash Advances Business Cash Advances utilize these tough times. Online personal need that the above fast Payday Cash Advance Payday Cash Advance in fast payday advance. Let our interest rate making at will get approved Cash Loans Online Cash Loans Online loan worry about repayment our specialty. Worse you unsecured they meet some major financial assistance Faxless Cash Loans Faxless Cash Loans program and interest credit records or office. Life just pouring gasoline on anytime of potential Quick Cash Loans Quick Cash Loans borrower might arrive that their feet. Opt for borrowers at reasonable amount next Payday Cash Loans Payday Cash Loans payday loan may come around. Wait in excess of an experienced a paystub Ease And Convenience Of The Fast Cash Network Ease And Convenience Of The Fast Cash Network bank that rarely check performed. Just fill out pages of years Cash Advance In One Hour Cash Advance In One Hour old in personal references. Conversely a bone and are turned take for Cash Advance Online fraud or credit even custom loans. Chapter is an unexpected car loan terms of Fast Cash Loan Laws Requirements Fast Cash Loan Laws Requirements arrangements are three major financial promises.
myCodeStudio
10Jan/1112

Core Animation

It's been a while since I did a post, but I've spent some time recently exploring different aspects of Core Animation for an upcoming app. One effect I wanted to achieve was a flip effect similar to the UIViewAnimationOptionTransitionFlipFromLeft or UIViewAnimationOptionTransitionFlipFromRight on UIView. The problem with these animated transitions is that they only work when swapping out a whole view for another. These transitions don't work on sub-views. So after much googling, there didn't seem to be an example of exacting what I needed so I put one together myself. I've posted a video on YouTube showing the effect I am after (sorry for the video quality!).

You can download the sample project from here, but the screenshots below show the transition in progress. Since Core Animation is focused around CALayers, my example creates to simple layers, one brown and one green, to transition between. The bottom scroll bar determines the amount of scaling that happens during the flip from one side to another - a positive setting makes it pop out towards the user. Setting this to 1.0 means the effect is just rotation around the y-axis (think of a playing card flipping from right to left around the middle), while a smaller number makes the side shrink during the flip. Click on one of the images to see the full application.

Now onto the code!

I started the example with a "View Based Application" iPhone template. First things first, be sure to QuartzCore.framework into your project to avoid build issues. The second thing to do is to include the QuartzCore header into any file that deals with Core Animation. In the example, this would be at the top of your ViewController.m file.

#import <QuartzCore/QuartzCore.h>

For this example, I create the two layers in the viewDidLoad function. I've rounded the corners to make it look a little nicer.

- (void)viewDidLoad {
	[super viewDidLoad];

	isFlipped = NO;

	topLayer= [CALayer layer];
	topLayer.doubleSided = NO;
	topLayer.name = @"1";
	topLayer.frame = CGRectMake(0.0f, 0.0f, 125.0f,125.0f);
	topLayer.position = CGPointMake(160.0f, 240.0f);
	topLayer.backgroundColor = [[UIColor brownColor] CGColor];
	[topLayer setCornerRadius:8.0f];
	[topLayer setMasksToBounds:YES];

	bottomLayer = [CALayer layer];
	bottomLayer.doubleSided = NO;
	bottomLayer.name = @"2";
	bottomLayer.frame = CGRectMake(0.0f, 0.0f, 125.0f,125.0f);
	bottomLayer.position = CGPointMake(160.0f, 240.0f);
	bottomLayer.backgroundColor = [[UIColor greenColor] CGColor];
	[bottomLayer setCornerRadius:8.0f];
	[bottomLayer setMasksToBounds:YES];

        // FIX for flipping over an image
        // Assuming this is over a background UIImageView (optional for folks)
        UIImageView* v = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Space-03.jpg"]];
        // add this as the root of the current view; you can do this in IB
        [self.view insertSubview:v atIndex:0];

        // now add the flipping layers to a different view, above the UI Image, but below the controls
        // defined in the XIB
        UIView* flipView = [[UIView alloc] initWithFrame:self.view.frame];
        [self.view insertSubview:flipView aboveSubview:v];
        [v release];

        // add bottom first; add to the NEW view, not self
	[flipView.layer addSublayer:bottomLayer];
	[flipView.layer addSublayer:topLayer];
        [flipView release];

        [self updateLabel];
}

Now that we have the two layers created, I set the Flip button to perform the animation.

- (IBAction) flip: (id) sender
{
	// if we currently transitioning, ignore any further taps on the button until we are done
	if (isTransitioning)
		return;
	// figure out which layer is the current visible one
	CALayer* top = topLayer;
	CALayer* bot = bottomLayer;

	if ( isFlipped ) {
		top = bottomLayer;
		bot = topLayer;
	}

	CAAnimation *topAnimation = [self flipAnimationWithDuration:1.0f forLayerBeginningOnTop:YES scaleFactor:self.slider.value];
	CAAnimation *bottomAnimation = [self flipAnimationWithDuration:1.0f forLayerBeginningOnTop:NO scaleFactor:self.slider.value];

	CGFloat zDistance = 1500.0f;
	CATransform3D perspective = CATransform3DIdentity;
	perspective.m34 = -1. / zDistance;
	top.transform = perspective;
	bot.transform = perspective;

	topAnimation.delegate = self;
	[CATransaction begin];
	[top addAnimation:topAnimation forKey:@"flip"];
	[bot addAnimation:bottomAnimation forKey:@"flip"];
	[CATransaction commit];
}

Where all the magic happens is in the flipAnimationWithDuration:forLayerBeginningOnTop:scaleFactor: function which creates the animation for the actual flip of the layer. If the scale is 1.0 then it skips the scaling part.

-(CAAnimation *)flipAnimationWithDuration:(NSTimeInterval)aDuration forLayerBeginningOnTop:(BOOL)beginsOnTop scaleFactor:(CGFloat)scaleFactor
{
	isTransitioning = YES;
	// Rotating halfway (pi radians) around the Y axis gives the appearance of flipping
	CABasicAnimation *flipAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];
	CGFloat startValue = beginsOnTop ? 0.0f : M_PI;
	CGFloat endValue = beginsOnTop ? -M_PI : 0.0f;
	flipAnimation.fromValue = [NSNumber numberWithDouble:startValue];
	flipAnimation.toValue = [NSNumber numberWithDouble:endValue];

 	// Shrinking the view makes it seem to move away from us, for a more natural effect
	// Can also grow the view to make it move out of the screen
 	CABasicAnimation *shrinkAnimation = nil;
    	if (self.slider.value != 1.0f ) {
        	shrinkAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
        	shrinkAnimation.toValue = [NSNumber numberWithFloat:scaleFactor];

        	// We only have to animate the shrink in one direction, then use autoreverse to "grow"
        	shrinkAnimation.duration = aDuration * 0.5;
        	shrinkAnimation.autoreverses = YES;
    	}

    	// Combine the flipping and shrinking into one smooth animation
    	CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
    	animationGroup.animations = [NSArray arrayWithObjects:flipAnimation, shrinkAnimation, nil];

    	// As the edge gets closer to us, it appears to move faster. Simulate this in 2D with an easing function
    	animationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
	animationGroup.duration = aDuration;

	// this really means keep the state of the object at whatever the anim ends at
	// if you don't do this then it reverts back to the original state (e.g. brown layer)
    	animationGroup.fillMode = kCAFillModeForwards;
    	animationGroup.removedOnCompletion = NO;

	return animationGroup;
}

Now to reset the state at after the animation is complete use the following function:

-(void)animationDidStop:(CAAnimation *)animation finished:(BOOL)flag
{
	isFlipped = !isFlipped;
	isTransitioning = NO;
}

Feel free to reuse the source as you see fit. Note the flip: and flipAnimationWithDuration:forLayerBeginningOnTop:scaleFactor: functions were modified from Drew McCormack's blog post for NSViews for the Mac. He placed his code in the public domain.

About Gary

No description. Please complete your profile.
Comments (12) Trackbacks (0)
  1. Thank you so much for the reference samples! That’s exactly what I was looking for

  2. Hello,
    thanks you very much for the nice core animation!
    But when I put a background image in the view, the flip animation don’t work perfectly.
    How can I fix this problem?

  3. how would i apply an image to these layers? i tried this with no joy
    topLayer.image =[UIImage imageNamed:@"pic.png"];

    any ideas??

  4. For images, I think you need to add to layer.contents. Check out the following as an example:
    http://www.raywenderlich.com/2502/introduction-to-calayers-tutorial

  5. Very good. you were write with layer.contents, its a good tutorial thanks for the help and much appreciated!

  6. Very good. you were right with layer.contents, its a good tutorial thanks for the help and much appreciated!

  7. Hmm… I see what you are talking about. Let me see what I can do to fix.

  8. When I use this code I get a ton of semantic error messages. I’m too new to iOS to even guess why and I know it can’t be the code since there are sooo many. Help a newbie understand what I’m doing wrong please? :)

  9. Fantastic tutorial! Would it take much to put a view on the back of the layer and have it ‘scale up’ to say 2x it’s original size when tapped ?

    I’m thinking it would be nice to have an effect similar to the iPad facebook or skype apps, which show views on the back of images when tapped… would like to know how they did that!

  10. Can you list what semantic issues you are having? Also, what version of XCode?

    Thanks,
    -Gary

  11. Hi Paul,

    I’m not sure if that would be possible since this animation is more at the CALayer level than at the UIView level (even though the latter has layers). Apple has some nice UIView animations, but they seem to be focused on swapping the whole view out (last time I checked). You could create a reverse-side using layout of a raw layer hierarchy (like a CALayer containing CATextLayer, etc).

    Sorry I couldn’t give a more definitive answer!
    -Gary

  12. Well I fixed the issues with flipping over an image. See the changes in the code above. I’ve pasted them here for quick reference. The basic idea is add the flip layers to a different UIView.

    UIImageView* v = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Space-03.jpg"]];
    [self.view insertSubview:v atIndex:0];

    UIView* top = [[UIView alloc] initWithFrame:self.view.frame];
    [self.view insertSubview:top aboveSubview:v];

    // add bottom first
    [top.layer addSublayer:bottomLayer];
    [top.layer addSublayer:topLayer];

    // update the scale label
    [self updateLabel];


Leave a comment


*

No trackbacks yet.