自定义动画以推送UIViewController

55
我想在推送视图控制器时显示自定义动画:我希望实现类似于“扩展”动画的效果,也就是说新视图在动画期间从给定的矩形,比如[100,100 220,380],扩展到全屏。
有什么建议或文档、教程、链接可以提供吗? :)
好的。我可以使用以下代码创建扩展动画:
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];

我的视图正确显示,但不幸的是导航栏没有更新。有没有手动更新的方法?


在示例代码中,每0.03秒调用一次函数以更新视图的变换。不幸的是,当推入一个UIViewController时,我无法调整视图框架的大小... 是吗?

6个回答

53

我使用下面这个函数(添加到 UINavigationController)来自定义推送动画:

- (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];
}

我猜你可以调整这段代码来完成你想要的任何动画效果。


2
不错,你是如何处理popViewController的情况的?据我所见,点击返回按钮不会调用任何给定的目标/选择器对,即使你重载了返回按钮并提供了一个,因此你不能将其设置为指向包含动画的自定义弹出方法? - crafterm
我记得曾经为自定义动画奋斗了一段时间,然后选择了一些不那么痛苦的解决方案。我不记得最终使用了什么,但可能类似于被接受的答案(或者我干脆放弃并使用了工厂转换)。 - zoul
UINavigationController上创建一个category似乎是个不错的选择。 - zoul
1
下面有一个答案,但我想在这里提一下,你可以轻松地使用popController来完成相同的操作。 - Hari Ganesan

34
你所寻找的代码是:
    [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];

如何处理popViewController场景? - Ans

25

您可以这样做:将下一个视图控制器推入,但不要对其进行动画处理:

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

然后,在被推入的视图控制器中,您可以使用CoreAnimation对其视图进行自定义动画。这可能最好在viewDidAppear:(BOOL)animated方法中完成。

查看Core Animation指南学习如何实际执行动画。特别关注隐式动画。

编辑:更新链接


3
我尝试过这种方法,但问题在于当你使用此推送时,第一个视图控制器在下一个控制器开始动画之前就会消失。 应该发生的是:1)下一个视图控制器进行动画,其视图完全覆盖旧vc的视图,然后旧vc弹出。 我正在编译iOS 4.3版本,但这并不起作用。 - Duck
1
这也不具有可扩展性。导航控制器应该处理动画。这是一种hack,您必须为每个被推送的视图控制器实现它。 - Austin Marusco

7

@zoul: 非常好用!我只是将“self”改为“self.navigationController”,将“self.view”改为“self.navigationController.view”。不知道是否必要,但它起作用了。至于返回上一页,@crafterm,只需在viewDidLoad或ViewWillAppear中添加以下代码即可创建自己的leftBarButtonItem:

//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];

然后我只是微调了push函数,并创建了这个popWithTransition函数,我在我的-backButtonTapped方法中调用它。

- (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];
}

注意,popViewController的调用被推迟到动画之后。不确定是否合适,但是它确实起作用了。

3
请查看 ADTransitionController,这是我们在 Applidium 创建的一个替代 UINavigationController 的自定义过渡动画组件(其 API 与 UINavigationController 相匹配)。
您可以使用不同的预定义动画来进行推送和弹出操作,例如 Swipe、Fade、Cube、Carrousel 等。 在您的情况下,您需要的动画是称为 Zoom 的动画。

3
你需要的是iphone开发者烹饪书第2章的下载内容。具体查看affineRotate示例,尽管任何核心动画示例都能帮到你。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接