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 ?

NightFury
  • 13,436
  • 6
  • 71
  • 120
Erik
  • 11,944
  • 18
  • 87
  • 126

6 Answers6

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.

zoul
  • 102,279
  • 44
  • 260
  • 354
  • 2
    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? – crafterm Jul 25 '10 at 08:35
  • 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). – zoul Jul 26 '10 at 10:45
  • A [category](http://www.google.com/search?q=objective-c+categories) on `UINavigationController` seems like a good place. – zoul Jun 13 '12 at 12:08
  • 1
    There's an answer [below](http://stackoverflow.com/a/3463625/1480438) with this, but I thought I'd mention here that you can easily do the same with `popController` – Hari Ganesan Feb 17 '14 at 20:35
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];
fyasar
  • 3,996
  • 2
  • 42
  • 55
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

Hari Ganesan
  • 532
  • 4
  • 18
imnk
  • 4,342
  • 3
  • 29
  • 31
  • 3
    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. – Duck Oct 05 '12 at 10:47
  • 1
    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. – Austin Marusco Jan 20 '14 at 03:39
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.

Nik Reiman
  • 39,067
  • 29
  • 104
  • 160
David
  • 81
  • 1
  • 4
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.

ennuikiller
  • 46,381
  • 14
  • 112
  • 137
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.

felginep
  • 51
  • 2