Custom Animation for Pushing a UIViewController
Asked Answered
M

6

55

I want to show a custom animation when pushing a view controller: I would like to achieve something like an "expand" animation, that means the new view expands from a given rectangle, lets say [100,100 220,380] during the animation to full screen.

Any suggestions where to start, respectively any documents, tutorials, links? :)


Alright. I could make the expand animation with the following code:

if ([coming.view superview] == nil)   
    [self.view addSubview:coming.view];
    coming.view.frame = CGRectMake(160,160,0,0);
    [UIView beginAnimations:@"frame" context:nil];
    [UIView setAnimationDuration:4];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
    [coming viewWillAppear:YES];
    [going viewWillAppear:YES];
    coming.view.frame = CGRectMake(0, 0, 320, 480);
    [going viewDidDisappear:YES];
    [coming viewDidAppear:YES];
    [UIView commitAnimations];

My View is properly displayed, but unfortunately the navigation bar is not updated. Is there a way to do that manually?


In the sample code, a function is called all 0.03 seconds that updates the transformation of the view. Unfortunately, when pushing a UIViewController, I am not able to resize the frame of the view ... am I ?

Matamoros answered 10/9, 2009 at 15:36 Comment(0)
C
25

What you could do is push the next view controller but don't animate it, like so:

[self.navigationController pushViewController:nextController animated:NO];

...and then, in the view controller that is getting pushed in, you could do a custom animation of it's view using CoreAnimation. This might be best done in the viewDidAppear:(BOOL)animated method.

Check out the Core Animation Guide on how to actually do the animation. Look particularly at the implicit animation.

EDIT: updated link

Cyanine answered 25/11, 2009 at 8:42 Comment(2)
I have tried this approach but the problem is that when you use this push, the first view controller vanishes before the next controller starts animating. What should happen is: 1) the next view controller animates and its view covers completely the old vc's view and then the old vc pops out. I am compiling for iOS 4.3 and this is not working.Permittivity
This isn't scalable too. A navigation controller should handle the animating. This is a hack that you would have to implement for every view controller being pushed.Chadchadabe
F
53

I use the following function (added to UINavigationController) to customize the push animation:

- (void) pushController: (UIViewController*) controller
         withTransition: (UIViewAnimationTransition) transition
{
    [UIView beginAnimations:nil context:NULL];
    [self pushViewController:controller animated:NO];
    [UIView setAnimationDuration:.5];
    [UIView setAnimationBeginsFromCurrentState:YES];        
    [UIView setAnimationTransition:transition forView:self.view cache:YES];
    [UIView commitAnimations];
}

I guess you could adapt this code to do whatever animation you want.

Foust answered 15/3, 2010 at 8:13 Comment(4)
Nice one, how do you handle the popViewController case? from what I can see, tapping the back button doesn't invoke any given target/selector pair even if you overload the back button and provide one, so you can't set it to point to a custom pop method that includes an animation?Enounce
I remember fighting with the custom animations for a while and then going for some less painful solution. I can’t remember what I ended up using, but it was probably something akin to the accepted answer (or I simply gave up and used a factory transition).Foust
A category on UINavigationController seems like a good place.Foust
There's an answer below with this, but I thought I'd mention here that you can easily do the same with popControllerSapota
N
34

The code which you are looking for:

    [UIView beginAnimations:@"View Flip" context:nil];
[UIView setAnimationDuration:0.80];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];

[UIView setAnimationTransition:
 UIViewAnimationTransitionFlipFromRight
                       forView:self.navigationController.view cache:NO];


[self.navigationController pushViewController:menu animated:YES];
[UIView commitAnimations];
Nyaya answered 3/9, 2010 at 21:54 Comment(1)
How to handle popViewController Scenario?Kuo
C
25

What you could do is push the next view controller but don't animate it, like so:

[self.navigationController pushViewController:nextController animated:NO];

...and then, in the view controller that is getting pushed in, you could do a custom animation of it's view using CoreAnimation. This might be best done in the viewDidAppear:(BOOL)animated method.

Check out the Core Animation Guide on how to actually do the animation. Look particularly at the implicit animation.

EDIT: updated link

Cyanine answered 25/11, 2009 at 8:42 Comment(2)
I have tried this approach but the problem is that when you use this push, the first view controller vanishes before the next controller starts animating. What should happen is: 1) the next view controller animates and its view covers completely the old vc's view and then the old vc pops out. I am compiling for iOS 4.3 and this is not working.Permittivity
This isn't scalable too. A navigation controller should handle the animating. This is a hack that you would have to implement for every view controller being pushed.Chadchadabe
A
7

@zoul: That worked great! I just changed "self" to "self.navigationController" and "self.view" to "self.navigationController.view" Don't know if that was necessary, but it worked. And @crafterm, as for popping back, just make your own leftBarButtonItem by adding this code in viewDidLoad or ViewWillAppear:

//add your own left bar button
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@"Back" style:UIBarButtonItemStylePlain target:self action:@selector(backButtonTapped)];
self.navigationItem.leftBarButtonItem = backButton;
[backButton release];

Then I just tweaked the push function and made this popWithTransition function that I called in my -backButtonTapped method.

- (void) popWithTransition: (UIViewAnimationTransition) transition
{
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:.75];
    [UIView setAnimationBeginsFromCurrentState:YES];        
    [UIView setAnimationTransition:transition forView:self.navigationController.view cache:YES];
    [UIView commitAnimations];
[self.navigationController popViewControllerAnimated:NO];
}

Note that the popViewController call got shifted down to the end, after the animation. Don't know if that's kosher, but again, it worked.

Applegate answered 11/8, 2010 at 23:23 Comment(0)
C
3

What you want is the downloads for chapter 2 of iphone developers cookbook. Look at the affineRotate sample specifically, although any of the core animatin samples will help you.

Colorimeter answered 10/9, 2009 at 15:54 Comment(0)
S
3

Have a look at ADTransitionController, a drop in replacement for UINavigationController with custom transition animations (its API matches the API of UINavigationController) that we created at Applidium.

You can use different pre-defined animations for push and pop actions such as Swipe, Fade, Cube, Carrousel and so on. In your case, the animation you are requesting is the one called Zoom.

Savoirvivre answered 17/7, 2013 at 13:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.