今天的文章中,我们来看看如何通过navigation controller的push和pops来实现淡入淡出的过渡。
Navigation Controller Delegate
在iOS中有着众多的协议,但是在这个例子当中我们只要讲其中一些我们要用的,并通过这个协议来完成交互转换和模式转换。
为了确定push或者pop的一个视图控制器是实现怎样的过渡,我们就要使得UINavigationController拥有一个委托,那就是UINavigationControllerDelegate这个协议,这里有四个新的过渡方法,
- (id <UIViewControllerAnimatedTransitioning>)navigationController:
animationControllerForOperation:
fromViewController:
toViewController:
这个方法将被反复调用,用于每个导航控制器和视图控制器之间的转换,(无论是通过代码或者是通过storyboard的segue),我们总是说通过视图控制器来实现从这里过渡到那里,所以究竟是什么形式的过渡方式都是由返回值决定的。
下面我们创建一个类作为导航控制器的委托:
@interface SCNavControllerDelegate: NSObject <UINavigationControllerDelegate>
下面是一个简单的实现
@implementation SCNacControllerDelegate
- (id<UIViewControllerAnimatedTransitioning>)
navigationController:(UINavigationController *)navigationContoller
animationControllerForOperation:(UINavigationControllerOperation)operation
fromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC
{
return [SCFadeTransition new];
}
我们希望所有的转换都是相同的(不管是正向或者是反向),所以我们可以只返回一个SCFadeTransition对象作为每一个过渡的返回值。让我们看看这是一个什么样对象:
设置这个委托是很简单的-就像我们在iOS中看到的其他的委托一样
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
_navDelegate = [SCNavControllerDelegate new];
self.delegate = _navDelegate;
}
return self;
}
这里的_navDelegate是id类型的<UINavigationControllerDelegate>
创建过渡转换
我们看到,委托需要返回过渡的对象,更具体的说就是它必须返回一个符合 UIViewControllerAnimatedTransitioning协议的对象。这个协议只有三个方法,两个是必须的。
transitionDuration:(必须)这里返回动画的持续时间,以便操作系统进行同步其他的事件。
animateTransition:(必须的) 这个方法是真的让你实现视图控制器之间的过渡的方法。我们提供一个对象就会给我们一个不同的组件,如果我们需要的话。
animationEnded:这个被称为:一旦转换完成,就允许你做任何你需要的整理
我们只要实现两个必须实现的方法,让我们实现淡入淡出的过渡。创建一个对象,采用这个协议
@interface SCFadeTransition: NSObject <UIViewControllerAnimateTransitioning>
transitionDuration的实现方法真的真的很简单
- (NSTimeInterval)transitionDUration:(id<UIViewControllerContextTransitioning>)transitionContext
{
return 2.0;
}
当animateTransitionL:这个方法被调用的时候,我们就会获得一个符合UIViewControllerContextTransitioning协议的对象,这样我们就获得了我们需要完成的动画的细节。我们将使用的第一种方法是:viewControllerForKey:这是我们能够掌握参与过渡的两个视图控制器。
//Get the two controllers
UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
这是通过访问ContainerView方法,来给我们提供执行动画的UIView
// 找到 container view - 动画在哪里发生
UIView *containerView = [transitionContext containerView];
我们需要确保每个视图都是containerView的子视图。也许我们在开始过渡的时候,就已经是子视图了,但是你仍要确保。
//在container中添加两个VC视图
[containerView addSubview:fromVC.view];
[containerView addSubview:toVC.view];
因为我们想要过渡的更加自然所以我们设置 alpha为0:
toVC.view.alpha =0.0;
现在,我们正在一个合适的位置来处理动画,由于我们正在做两个视图之间的一个简单的淡入淡出,我们可以使用一个UIView动画块:
[UIView animatedWithDuration:[self transitionDUration:transitionContext]
delay:0
options:0
aninmations:^{ toVC.view.alpha = 1.f;}
completion:^(BOOL finished) {
//让我们清除老的VC view
[fromVC.view removeFromSuperview];
//剩下的就是高度context我们已经完成了
[transitionContext completeTransition:YES];
}
];
注意要点: 我们设定的期限是一样的transitionDuration :方法我们已经实现。 - 与相关的视图中的“from”视图控制器需要从视图层次结构中移除,一旦过渡完成。 这个completeTransition :方法就会告知操作系统,我们已经完成了被调用。
你可以在这里找到相关文件:github.com/ShinobiControls/ios7-day-by-day4