iOS自定义转场动画例程与需要注意的问题
OS提供了一些内置的转场类型。Navigation controllers用push和pop来有层次地导航信息,tab bar controllers用切换tabs来在各部分之间跳转,所有的视图控制器可以根据特定任务模态化地present和dismiss另一个视图控制器。
API介绍
每一个自定义转场涉及三个主要对象:
from view controller (消失的那个)
to view controller (出现的那个)
一个动画控制器
自定义转场和在自定义之前一样。对于push和pop,意味着调用UINavigationController的push-、pop-、或者set-方法来修改视图控制器的堆栈。对于切换tabs,意味着修改UITabBarController的selectedIndex或selectedViewController属性。对于modal,则意味着调用?[UIViewController presentViewController: animated: completion: ]或?[UIViewController dismissViewControllerAnimated: completion: ]。无论哪种情况,这个步骤都确定了“from view controller”和“to view controller”。
使用一个自定义转场,你需要一个动画控制器。对我来说这是自定义动画转场中最令人困惑的部分,因为每种转场需要的动画控制器不同。下表展示了如何为每种转场提供动画控制器。记着,委托方法总是返回动画控制器。
动画控制器可以是任何遵守UIViewControllerAnimatedTransitioning协议的对象。该协议声明了两个必须要实现的方法。一个提供了动画的时间,另一个执行了动画。这些方法调用时都传递一个上下文。上下文提供了入口来访问信息和你创建自定义转场需要的对象。以下是一些重点:
from view controller
to view controller
两个视图控制器view的第一帧和最后一帧
container view,根据这篇文档,“作为的转场中视图的父视图”
重要:上下文还实现了-completeTransition:,你必须在你自定义转场结束时调用一次。
这是关于自定义转场所有你需要知道的。让我们来看一些例子!
例子
所有这些例子都可以在GitHub找到,你可以克隆这些仓库,然后边往下看边试试这些例子。
这三个例子都直接或子类化地使用了TWTExampleViewController。它只是设置了视图的背景颜色,同时使你能够通过点击任何地方来结束例子回到主菜单。
轻弹push和pop
在这个例子中,目标是让push和pop使用flip动画而不是标准的slide动画。一开始我建立一个navigation controller并把TWTPushExampleViewController的实例当作root。TWTPushExampleViewController添加了一个叫“Push”的右按钮到导航栏。点击它时,一个新的TWTPushExampleViewController的实例被压入navigation的堆栈:
- (void)pushButtonTapped
{
TWTPushExampleViewController *viewController = [[TWTPushExampleViewController alloc] init];
viewController.delegate = self.delegate;
[self.navigationController pushViewController:viewController animated:YES];
}
navigation controller的设置发生在TWTExamplesListViewController(运行demo主菜单的视图控制器)。注意,它把自己置为navigation controller的委托:
- (void)presentPushExample
{
TWTPushExampleViewController *viewController = [[TWTPushExampleViewController alloc] init];
viewController.delegate = self;
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
navigationController.delegate = self;
[self presentViewController:navigationController animated:YES completion:nil];
}
这意味着当navigation controller的转场即将开始时,TWTExamplesListViewController将收到委托信息,并有机会返回一个动画控制器。对于这种转场,我使用一个TWTSimpleAnimationController的实例,它是一个+[UIView transitionFromView: toView: duration: options: completion:]的封装:
- (id)navigationController:(UINavigationController *)navigationController
animationControllerForOperation:(UINavigationControllerOperation)operation
fromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC
{
TWTSimpleAnimationController *animationController = [[TWTSimpleAnimationController alloc] init];
animationController.duration = 0.5;
animationController.options = ( operation == UINavigationControllerOperationPush
? UIViewAnimationOptionTransitionFlipFromRight
: UIViewAnimationOptionTransitionFlipFromLeft);
returnanimationController;
}
如果转场是一个push,我使用一个从右侧的flip,否则,我使用一个从左侧的flip。
以下是TWTSimpleAnimationController的实现:
- (NSTimeInterval)transitionDuration:(id)transitionContext
{
returnself.duration;
}
- (void)animateTransition:(id)transitionContext
{
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
toViewController.view.frame = [transitionContext finalFrameForViewController:toViewController];
[toViewController.view layoutIfNeeded];
[UIView transitionFromView:fromViewController.view
toView:toViewController.view
duration:self.duration
options:self.options
completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}
记着,这两个方法是UIViewControllerAnimatedTransitioning协议的一部分。在动画控制器运行自定义转场的时候,它们被UIKit调用。
这里有一些关于animateTransition:需要注意的事情:
from view controller,to view controller,以及to view controller的最后一帧都从转场的上下文中提取。其中还有一些其他可提取的信息,但在当前情况下,并不需要所有信息。
+[UIView transitionFromView: toView: duration: options: completion:]负责有层次地添加和删除视图。在后面的例子中,我将展示一种手动完成的情况。
在转场的completion代码块中,我调用[transitionContext completeTransition: YES]来告诉系统转场结束了。如果你忘了这样做,你将无法与app交互。如果出现这种情况,先检查这个原因。
以上就是全部!现在有一些值得尝试的东西:
改变动画的持续时间来看看它如何影响navigation bar的动画。
把动画选项由flip改为page curls。
找一个方法让navigation的堆栈中的每个视图控制器能指定自己的动画控制器。看看在本文最后的推荐模式中提出的方法。
非常好我支持^.^
(0) 0%
不好我反对
(0) 0%