iOS--UINavigationController学习笔记三

1.UINavigationControllerDelegate之push/pop转场动画

       在iOS7之后,果爹就提供了可以自定义转场动画。包括navigation的push/pop动画,present/dismiss的动画。定制Push/Pop转场动画,首先需要了解iOS7中提供的几个方法和协议。比较重要的几个协议有: UIViewControllerContextTransitioning;UIViewControllerAnimatedTransitioning
       UIViewControllerContextTransitioning通常情况下不需要自己进行实现的,在push/pop中系统会自己创建一个转场的上下文,在上下文可以拿到转场前后的UIViewController,从而拿到转场前后的view;该协议中,存在一个containerView是用来将转场前后的view添加进去来进行具体动画初始frame和最后frame的设置。
       UIViewControllerAnimatedTransitioning其实是转场动画的实施者,动画的具体形式,时间都是通过这个协议设置的,自定义的主要内容。
       - ( nullable id )navigationController:(UINavigationController *)navigationController   animationControllerForOperation:(UINavigationControllerOperation)operation  fromViewController:(UIViewController *)fromVC  toViewController:(UIViewController *)toVC  NS_AVAILABLE_IOS(7_0);
    上面这个方法就是UINavigationControllerDelegate的一个协议方法,就是告诉UINavigationController在进行转场时,到底用的是哪个实施者。

2.push/pop转场动画Demo

     (1)首先创建一个类实现UIViewControllerAnimatedTransitioning协议,代码如下,第一个方法是设置动画持续的时间;第二个方法才是具体的动画过程:先通过UIViewControllerContextTransitioning的实例获得前后的viewController以及对应的view。然后把后面的viewController加到UIViewControllerContextTransitioning的containerView之上,之后就可以随心所欲的设置动画过程了(没有做不到的动画,只有你想不到的动画)。Demo 中Push和Pop分别是显隐动画和frame的动画。在动画的结束中,需要有[transitionContext completeTransition:YES]的调用,通知转场动画的结束,否则会出现bug。

- ( NSTimeInterval )transitionDuration:( id < UIViewControllerContextTransitioning >)transitionContext
{
   
return 0.8 ;
}

- (
void )animateTransition:( id < UIViewControllerContextTransitioning >)transitionContext
{
    UIViewController* fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController * toViewController = [transitionContext viewControllerForKey : UITransitionContextToViewControllerKey ];
   
NSTimeInterval duration = [ self transitionDuration :transitionContext];
   
UIView * containerView = [transitionContext containerView ];
   
switch ( self . operation ) {
       
case UINavigationControllerOperationPush :
        {
           
CGRect frame = CGRectMake ( 0 , 0 ,[ UIScreen mainScreen ]. bounds . size . width ,[ UIScreen mainScreen ]. bounds . size . height );
            toViewController.view.frame= frame;
            [containerView addSubview :toViewController. view ];
            toViewController.
view . alpha = 0.0 ;
            [
UIView animateWithDuration :duration
                            
animations :^{
                                 toViewController.
view . alpha = 1.0 ;
                             }
completion :^( BOOL finished) {
                                 [fromViewController.
view removeFromSuperview ];
                                 [transitionContext
completeTransition : YES ];
                             }];
        }
           
break ;
           
       
case UINavigationControllerOperationPop :
        {
            [containerView
insertSubview :toViewController. view belowSubview :fromViewController. view ];
           
CGRect frame = [transitionContext initialFrameForViewController :fromViewController];
            fromViewController.
view . frame = frame;
            [
UIView animateWithDuration :duration
                            
animations :^{
                                 fromViewController.
view . frame = CGRectMake ( 0 , frame. origin . y + [ UIScreen mainScreen ]. bounds . size . height , frame. size . width , frame. size . height );
                             }
completion :^( BOOL finished) {
                                 [fromViewController.
view removeFromSuperview ];
                                 [transitionContext
completeTransition : YES ];
                             }];
        }
           
break ;
           
       
default :
           
break ;
    }
}

(2)将这个实现UIViewControllerAnimatedTransitioning的类的实例赋值给UINavigationController的delegate的回调方法。代码如下:

- ( id < UIViewControllerAnimatedTransitioning >)navigationController:( UINavigationController *)navigationController animationControllerForOperation:( UINavigationControllerOperation )operation fromViewController:( UIViewController *)fromVC toViewController:( UIViewController *)toVC
{
   
if (! _manager ) {
       
_manager = [ CyPushPopManager new ];
    }
   
_manager . operation = operation;
   
return _manager ;
}

(3)效果如下
                              

iOS--UINavigationController学习笔记三_第1张图片
3.push/pop转场动画的tips

        在iOS7中,UINavigationController中有一个interactivePopGestureRecognizer的属性,支持APP的滑动返回这个功能。但是,在自定义UINavigationController过程,或者是自定义UIViewController的leftBarButtonItem就会导致这个gesture失效。解决方案: self . interactivePopGestureRecognizer . delegate = ( id ) self ;重新复制这个gesture的delegate给self就OK了。愿意还不懂。 

你可能感兴趣的:(iOS--UINavigationController学习笔记三)