开发者

How to implement UIView transition

I have an app which has a start screen with a start button on it. If you tap that button the view changes and a new view appears, let's call that main view.

The way I implemented it is one view controller per view. Now that I want to add transition animations this implementation causes problems. For example, I want to use the following code:

[UIView transitionFromView:startView toView: mainView duration: 2.0 
 options: UIViewAnimationOptionTransitionCurlDown completion: NULL];

But this doesn't do anything. Reading the documentation suggests that this only works if the view controller doesn't change. The documentation doesn't have any examples of a curl down transit开发者_如何转开发ion where the view controllers change so I'm not sure what to do.

When I started writing the app I read the guidelines and they suggested that having one view controller per view is the correct way of doing what I'm doing.

Now what is the correct way to implement a view transition when the view controller changes too? Many thanks for your help!

Edit: I am looking for a solution where the first view controller is destroyed.


It was proposed that you effectively create a view controller, use its view, but then disregard the controller itself. This is not advised. In iOS you want to keep your view controller hierarchy synchronized with your view hierarchy. Any techniques like the one proposed are therefore problematic. (WWDC 2011 session 102, while on a different topic, view controller containment, has a lengthy discussion of the importance of keeping these two hierarchies synchronized.)

The most obvious problem is that certain events, notably rotation events, are not going to transmitted successfully to your new controller and you can get some very strange results. It's also not clear with your code above what happens with the old view that you removed, how you would transition back, how you'd clean up the now unnecessary game controller, what would happen on didReceiveMemoryWarning if you were in the game controller, etc. This just seems to introduce a ton a problems.

The easiest solution is apply standard pushViewController and/or presentViewController calls to go from one view to another, and just animate those transitions. If you have questions about either of those methods, or how to animate within the context of those methods, let me know.


By the way, the root of your question was how to transition between view controllers. Here is a old collection of transitions (some for push transitions, some for modal transition) that I was once playing around with. Maybe there's something here that you could use?

- (void)transitionToNewController
{
    MyViewController *controller = [[MyViewController alloc] initWithNibName:@"MyView" bundle:nil];

#if TRANSITIONTYPE == 1

    // pushViewController with push/slide from right via CATransition

    CATransition* transition = [CATransition animation];

    transition.duration = 0.3;
    transition.type = kCATransitionPush;
    transition.subtype = kCATransitionFromRight;

    [self.navigationController.view.layer addAnimation:transition forKey:kCATransition];
    [self.navigationController pushViewController:controller animated:NO];
#endif

#if TRANSITIONTYPE == 2

    // pushViewController with flip using UIView begin/commitAnimations

    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
    [UIView setAnimationDuration:0.75];
    [self.navigationController pushViewController:controller animated:NO];
    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.navigationController.view cache:NO];
    [UIView commitAnimations];
#endif

#if TRANSITIONTYPE == 3

    // pushViewController with flip using animation block

    [UIView animateWithDuration:0.5 
                     animations:^{
                         [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
                         [self.navigationController pushViewController:controller animated:NO];
                         [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.navigationController.view cache:NO];
                     }
                     completion:nil];

#endif

#if TRANSITIONTYPE == 4

    // pushViewController with fade via CATransition

    CATransition* transition = [CATransition animation];

    transition.duration = 0.5;
    transition.type = kCATransitionFade;

    [self.navigationController.view.layer addAnimation:transition forKey:kCATransition];
    [self.navigationController pushViewController:controller animated:NO];
#endif

#if TRANSITIONTYPE == 5

    // pushViewController with fade via animation block

    controller.view.alpha = 0.0f;

    [UIView animateWithDuration:0.5 
                     animations:^{
                         self.view.alpha = 0.0f;
                         controller.view.alpha = 1.0f;
                     }
                     completion:^(BOOL finished){
                         [self.navigationController pushViewController:controller animated:NO];
                         self.view.alpha = 1.0f; // reset the src alpha so it's there when you pop your view controller off
                     }];
#endif

#if TRANSITIONTYPE == 6

    // pushViewController Flip using UIView begin/commitAnimations

    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
    [UIView setAnimationDuration:0.75];
    [self.navigationController pushViewController:controller animated:NO];
    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:[self.self navigationController].view cache:NO];
    [UIView commitAnimations];
#endif

#if TRANSITIONTYPE == 7

    // pushViewController animation using CGAffine scale to look like we're zooming into the new view

    [self.view addSubview:controller.view];
    [controller.view setFrame:self.view.window.frame];
    [controller.view setTransform:CGAffineTransformMakeScale(0.5,0.5)];
    [controller.view setAlpha:1.0];

    [UIView animateWithDuration:0.5
                          delay:0.0
                        options:UIViewAnimationCurveEaseOut 
                     animations:^{
                         [controller.view setTransform:CGAffineTransformMakeScale(1.0,1.0)];
                         [controller.view setAlpha:1.0];
                     } 
                     completion:^(BOOL finished){
                         [controller.view removeFromSuperview];
                         [self.navigationController pushViewController:controller animated:NO];
                     }];
#endif

#if TRANSITIONTYPE == 8

    // presentViewController animation with slide from right by using CGAffineTransform

    self.view.transform = CGAffineTransformMakeTranslation(0, 0);
    controller.view.transform = CGAffineTransformMakeTranslation(self.view.frame.size.width, 0);
    [self.view addSubview:controller.view];

    [UIView animateWithDuration:4.0
                     animations:^{
                         //                         [self presentViewController:controller animated:NO completion:nil];
                         self.view.transform = CGAffineTransformMakeTranslation(self.view.frame.size.width, 0);
                         controller.view.transform = CGAffineTransformMakeTranslation(0, 0);
                     }
                     completion:^(BOOL finished){
                         [controller.view removeFromSuperview];
                         [self presentViewController:controller animated:NO completion:nil];
                     }
     ];
#endif

#if TRANSITIONTYPE == 9

    // presentViewController animation with slide from right by just animating frames

    float width = self.navigationController.view.frame.size.width;

    CGPoint right = controller.view.center;
    right.x += width;
    controller.view.center = right;

    [self.navigationController.view addSubview:controller.view];

    [UIView animateWithDuration:0.5
                     animations:^{
                         CGPoint left = self.navigationController.view.center;
                         left.x -= width;
                         self.navigationController.view.center = left;
                     }
                     completion:^(BOOL finished){
                         [controller.view removeFromSuperview];
                         [self presentViewController:controller animated:NO completion:nil];
                     }
     ];
#endif

#if TRANSITIONTYPE == 10

    // presentViewController animation with flipfromright

    [UIView animateWithDuration:4.0
                          delay:0.0 
                        options:UIViewAnimationOptionTransitionFlipFromRight 
                     animations:^{
                         [self.view addSubview:controller.view];
                     }
                     completion:^(BOOL finished){
                         [controller.view removeFromSuperview];
                         [self presentViewController:controller animated:NO completion:nil];
                     }];
#endif

#if TRANSITIONTYPE == 11

    // presentViewController with flip using UIView begin/commitAnimations

    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
    [UIView setAnimationDuration:0.75];
    [self presentViewController:controller animated:NO completion:nil];
    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:NO];
    [UIView commitAnimations];
#endif

#if TRANSITIONTYPE == 13

    // pushViewController with flip using animation block with transitionWithView

    controller.view.frame = self.view.window.frame;

    [UIView transitionWithView:self.view.superview 
                      duration:1.0
                       options:UIViewAnimationTransitionFlipFromRight
                    animations:^{
                        [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
                        [self.view.superview addSubview:controller.view];
                        [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.navigationController.view cache:NO];
                    }
                    completion:^(BOOL finished){
                        [self.navigationController pushViewController:controller
                                                             animated:NO];
                    }];

#endif

}


Okey-doke, I found a neat way to achieve exactly what I want. This code, added in the method where I exchange the old view controller and view with the new one, works great:

GameViewController *game = [[GameViewController alloc] init];
UIView *currentView = [currentViewController view];
// remove the current view and replace with myView1
[currentView removeFromSuperview];
// set up an animation for the transition between the views
CATransition *animation = [CATransition animation];
[animation setDuration:0.5];
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromBottom];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]]; 
[[window layer] addAnimation:animation forKey:@"SwitchToView1"];    
[self setCurrentViewController: game];
[window addSubview:[currentViewController view]];
[game release];

Many thanks to HERE!!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜