iOS自定义转场动画,自定义iOS交互式转场动画的

作者: 工程材料  发布:2019-10-04

简介

VCTransitionsLibrary 提供了许多适用于入栈,出栈,模态等场景下控制器切换时的转场动画.它本身提供了一个定义好的转场动画库,你可以拖到自己工程中直接使用;也提供了许多拥有不同转场动画效果”互动控制器”,你可以直接使用这些控制器来和自定义动画效果配合使用;而不是自己控制去控制交互.

项目主页: VCTransitionsLibrary

最新示例: 点击下载

注意: 自定义视图控制器的转场动画为iOS7 + 通过 UIViewControllerTransitioningDelegate协议, UINavigationControllerDelegate协议和 UITabBarControllerDelegate 协议提供的系统级别的支持.这个库的意义在于定义了常用的动画效果,并封装了常用的交互操作,简化了iOS交互式转场动画的编码量!

VCTransitionsLibrary –自定义iOS交互式转场动画的库,ios转场动画

所谓的转场动画, 在iOS中随处可见, 通过 presentViewController:animated:completion: 和dismissViewControllerAnimated:completion: 这一组函数以模态视图的方式展现、隐藏视图.  通过调用 pushViewController:animated: 和popViewController 这一组函数将新的视图控制器压栈、弹栈.

快速入门

简介

VCTransitionsLibrary 提供了许多适用于入栈,出栈,模态等场景下控制器切换时的转场动画.它本身提供了一个定义好的转场动画库,你可以拖到自己工程中直接使用;也提供了许多拥有不同转场动画效果”互动控制器”,你可以直接使用这些控制器来和自定义动画效果配合使用;而不是自己控制去控制交互.

项目主页: VCTransitionsLibrary

最新示例: 点击下载

注意: 自定义视图控制器的转场动画为iOS7 + 通过 UIViewControllerTransitioningDelegate协议, UINavigationControllerDelegate协议和 UITabBarControllerDelegate 协议提供的系统级别的支持.这个库的意义在于定义了常用的动画效果,并封装了常用的交互操作,简化了iOS交互式转场动画的编码量!

但是, 想实现类似下面比较"复杂, 炫酷"的动画, 不用到自定义的转场动画是基本不可能实现的.

运行环境

  • iOS 7+
  • ARC

快速入门

奇幻电玩城游戏下载 1

安装

运行环境

  • iOS 7+
  • ARC

演示

使用 CocoaPods 安装

pod "VCTransitionsLibrary"

安装

那么接下来, 让我们一起看看自定义转场动画到底有什么奇妙的地方以及该如何实现一个自定义转场动画.

手动安装

把文件 AnimationControllers 和 InteractionControllers 文件夹下所有代码复制到工程中即可.

使用 CocoaPods 安装

pod "VCTransitionsLibrary"

From和To

在自定义转场动画的代码中,经常会出现fromViewController和toViewController。如果错误的理解它们的含义会导致动画逻辑完全错误。fromViewController表示当前视图容器,toViewController表示要跳转到的视图容器。如果是从A视图控制器present到B,则A是from,B是to。从B视图控制器dismiss到A时,B变成了from,A是to。用一张图表示:

注: iOS8之后可以直接通过 UITransitionContextFromViewKey 和 UITransitionContextToViewKey 获取到fromView 和 toView

奇幻电玩城游戏下载 2

from 和 to

使用

在自定义转场动画时,有两类关键的类:

  • 动画控制器 –  这个类是用来实现自定义动画的.但你声明想要使用自定义动画时,你应该提供一个动画控制器.这个类会实现需要的动画,完成时会通知框架.
  • 交互控制器 – 这个类是用来管理交互的-那些通常由某个手势空控制的交互,允许用户通过滑动,轻扫或执行其他操作来实现两个视图控制器的导航.必须指出的是,交互控制器允许导航取消,例如,一个用户可以在正在导航至某一页面时,突然改变主意,然后取消了操作.

注意: 动画和交互是完全独立的,这意味着你可以在其他任何自定义控制器上独立使用交互控制器-很酷!

手动安装

把文件 AnimationControllers 和 InteractionControllers 文件夹下所有代码复制到工程中即可.

Presented和Presenting

这也是一组相对的概念,它容易与fromView和toView混淆。简单来说,它不受present或dismiss的影响,如果是从A视图控制器present到B,那么A总是B的presentingViewController, B总是A的presentedViewController。

使用动画控制器

AnimationControllers 文件夹中提供了许多可以整合进你的工程中的动画控制器:

使用

在自定义转场动画时,有两类关键的类:

  • 动画控制器 –  这个类是用来实现自定义动画的.但你声明想要使用自定义动画时,你应该提供一个动画控制器.这个类会实现需要的动画,完成时会通知框架.
  • 交互控制器 – 这个类是用来管理交互的-那些通常由某个手势空控制的交互,允许用户通过滑动,轻扫或执行其他操作来实现两个视图控制器的导航.必须指出的是,交互控制器允许导航取消,例如,一个用户可以在正在导航至某一页面时,突然改变主意,然后取消了操作.

注意: 动画和交互是完全独立的,这意味着你可以在其他任何自定义控制器上独立使用交互控制器-很酷!

modalPresentationStyle

这是一个枚举类型,表示present时动画的类型。其中可以自定义动画效果的只有两种:FullScreen和Custom,两者的区别在于FullScreen会移除fromView,而Custom不会。比如文章开头的gif中,第三个动画效果就是Custom。

自定义模态控制器显示/隐藏的动画

UIViewControllerTransitioningDelegate 协议被用来在模态控制器显示/隐藏时提供一个动画控制器.当一个视图控制器被模态显示或隐藏时,它的transitioningDelegate属性用来提供UIViewControllerTransitioningDelegate协议的支持.担当代理角色的类,通过 animationControllerForPresentedController: presentingController: sourceController: 方法返回模态显示时的动画, 通过 animationControllerForDismissedController: 返回模态消失时的动画即可.

使用动画控制器

AnimationControllers 文件夹中提供了许多可以整合进你的工程中的动画控制器:

基于block的动画

最简单的转场动画是使用transitionFromView方法:

奇幻电玩城游戏下载 3

系统自带UIView转场动画

这个系统再带的UIView转场动画一共有5个参数,前两个表示从哪个view开始,跳转到哪个view,中间两个参数表示动画的时间和选项。最后两个参数表示动画的具体实现细节和回调闭包。(虽然没有出现UIViewController, 但可以帮助我们分析自定义转场动画)

这5个参数其实就是一次转场动画所必备的5个元素。它们可以分为两组,前两个参数为一组,表示页面的跳转关系,后面3个为一组,表示动画的执行逻辑。

奇幻城娱乐app,这个方法的缺点之一是可自定义程度不高(在后面您会发现能自定义的不仅仅是动画方式),另一个缺点则是重用性不好,也可以说是耦合度比较大。

在最后一个闭包参数中,可以预见的是fromView和toView参数都会被用到,而且他们是动画的关键。假设视图A可以跳转到B、C、D、E、F,而且跳转动画基本相似,你会发现transitionFromView方法要被复制多次,每次只会修改少量内容。

自定义顶部导航的转场动画

UINavigationController 有一个

id<UINavigationControllerDelegate> delegate 属性.只需要让它的代理通过 navigationController: animationControllerForOperation: fromViewController: toViewController: 返回某个动画效果即可.

为了同时设置出栈/入栈都合适的动画效果(或者说,出栈/入栈时能使用相反方向的动画),你可以参考下面代码:

- (id<UIViewControllerAnimatedTransitioning>)navigationController:
                                (UINavigationController *)navigationController
   animationControllerForOperation:(UINavigationControllerOperation)operation
                fromViewController:(UIViewController *)fromVC
                  toViewController:(UIViewController *)toVC {

    // 出栈时,要反转动画方向.
    _animationController.reverse = operation == UINavigationControllerOperationPop;

    return _animationController;
}

自定义模态控制器显示/隐藏的动画

UIViewControllerTransitioningDelegate 协议被用来在模态控制器显示/隐藏时提供一个动画控制器.当一个视图控制器被模态显示或隐藏时,它的transitioningDelegate属性用来提供UIViewControllerTransitioningDelegate协议的支持.担当代理角色的类,通过 animationControllerForPresentedController: presentingController: sourceController: 方法返回模态显示时的动画, 通过 animationControllerForDismissedController: 返回模态消失时的动画即可.

自定义present转场动画

出于解耦和提高可自定义程度的考虑,我们来学习转场动画的正确使用姿势。

首先要了解一个关键概念:转场动画代理,它是一个实现了UIViewControllerTransitioningDelegate协议的对象。我们需要自己实现这个对象,它的作用是为UIKit提供以下几个对象中的一个或多个:

Animator:

它是实现了UIViewControllerAnimatedTransitioning协议的对象,用于控制动画的持续时间和动画展示逻辑,代理可以为present和dismiss过程分别提供Animator,也可以提供同一个Animator。

交互式Animator:和Animator类似,不过它是交互式的,后面会有详细介绍

奇幻电玩城游戏下载,Presentation控制器:

它可以对present过程更加彻底的自定义,比如修改被展示视图的大小,新增自定义视图等,后面会有详细介绍。

奇幻电玩城游戏下载 4

转场动画代理

在这一小节中,我们首先介绍一个最简单的Animator。回顾一下转场动画必备的5个元素,它们被分为两组,彼此之间没有关联。Animator的作用等同于第二组的三个元素,也就是说对于同一个Animator,可以适用于A跳转B,也可以适用于A跳转C。它表示一种通用的页面跳转时的动画逻辑,不受限于具体的视图控制器。

如果您读懂了这段话,整个自定义的转场动画逻辑就很清楚了,以视图控制器A跳转到B为例:

创建动画代理,在事情比较简单时,A自己就可以作为代理

设置B的transitioningDelegate为步骤1中创建的代理对象

调用presentViewController:animated:completion:并把参数animated设置为YES

系统会找到代理中提供的Animator,由Animator负责动画逻辑

用具体的例子解释就是:

@interface ViewController() <UIViewControllerTransitioningDelegate, SecondViewControllerDelegate>

@end

// 这个类相当于A

@implementation ViewController

- (void)viewDidLoad {

[superviewDidLoad];

}

- (IBAction)jumoToNextVC {

// 这个对象相当于B

SecondViewController *viewController = [[UIStoryboardstoryboardWithName:@"Main"bundle:nil]instantiateViewControllerWithIdentifier:@"SecondViewController"];

viewController.modalPresentationStyle = UIModalPresentationCustom;

viewController.transitioningDelegate = self;

viewController.delegate = self;

[self presentViewController:viewController animated:YES completion:nil];

}

// 下面这两个函数定义在UIViewControllerTransitioningDelegate协议中,  用于为present和dismiss提供animator

- (id)animationControllerForPresentedController:(UIViewController*)presented presentingController:(UIViewController*)presenting sourceController:(UIViewController*)source{

return [[CustomPresentAnimationalloc]init];

}

- (id)animationControllerForDismissedController:(UIViewController*)dismissed{

return [[CustomDismissAnimationalloc]init];

}

// 对象B的代理方法

- (void)selectedBackButton{

[selfdismissViewControllerAnimated:YEScompletion:nil];

}

@end

动画的关键在于animator如何实现,它实现了UIViewControllerAnimatedTransitioning协议,至少需要实现两个方法,它是整个动画逻辑的核心:

新建一个类, 继承自NSObject, 遵守了 UIViewControllerAnimatedTransitioning 协议. 如下: 

奇幻电玩城游戏下载 5

animator 的 .h

UIViewControllerAnimatedTransitioning 是整个自定义转场动画的核心. 接下来看看.m实现文件: 

奇幻电玩城游戏下载 6

animator 的 .m

方法1: 返回了该自定义动画的持续时间.

方法2(重点): 核心是从转场动画上下文获取必要的信息以完成动画。上下文containerView是一个实现了UIViewControllerContextTransitioning的对象,它的作用在于为animateTransition方法提供必备的信息。你不应该缓存任何关于动画的信息,而是应该总是从转场动画上下文中获取(比如fromView和toView),这样可以保证总是获取到最新的、正确的信息.

奇幻电玩城游戏下载 7

转场动画上下文

获取到足够信息后,我们调用[UIView animateWithDuration...]方法把动画交给Core Animation处理。不要忘记在动画调用结束后,执行completeTransition方法。

present时,要把toView加入到container的视图层级。

dismiss时,要把fromView从container的视图层级中移除。

总结: 

设置将要跳转到的视图控制器(presentedViewController)的transitioningDelegate

充当代理的对象可以是源视图控制器(presentingViewController),也可以是自己创建的对象,它需要为转场动画提供一个animator对象。

animator对象的animateTransition是整个动画的核心逻辑。

自定义底部标签栏导航的转场动画

UITabBarController 有一个 id<UITabBarControllerDelegate> delegate属性,只需要让它的代理通过tabBarController: animationControllerForTransitionFromViewController: toViewController:返回某个动画效果即可.

为了给动画一个合适的方向,你可以比较两个视图控制器的索引:

- (id <UIViewControllerAnimatedTransitioning>)tabBarController:(UITabBarController *)tabBarController
            animationControllerForTransitionFromViewController:(UIViewController *)fromVC
                                              toViewController:(UIViewController *)toVC {

    NSUInteger fromVCIndex = [tabBarController.viewControllers indexOfObject:fromVC];
    NSUInteger toVCIndex = [tabBarController.viewControllers indexOfObject:toVC];

    _animationController.reverse = fromVCIndex < toVCIndex;
    return _animationController;
}

自定义顶部导航的转场动画

UINavigationController 有一个

id<UINavigationControllerDelegate> delegate 属性.只需要让它的代理通过 navigationController: animationControllerForOperation: fromViewController: toViewController: 返回某个动画效果即可.

为了同时设置出栈/入栈都合适的动画效果(或者说,出栈/入栈时能使用相反方向的动画),你可以参考下面代码:

- (id<UIViewControllerAnimatedTransitioning>)navigationController:
                                (UINavigationController *)navigationController
   animationControllerForOperation:(UINavigationControllerOperation)operation
                fromViewController:(UIViewController *)fromVC
                  toViewController:(UIViewController *)toVC {

    // 出栈时,要反转动画方向.
    _animationController.reverse = operation == UINavigationControllerOperationPop;

    return _animationController;
}

UINavigationController转场动画

其实UINavigationController也可以自定义转场动画。两者是平行关系,很多都可以类比过来:

奇幻电玩城游戏下载 8

遵循代理

奇幻电玩城游戏下载 9

设置代理对象为self

与present/dismiss不同的时,现在视图控制器实现的是UINavigationControllerDelegate协议,让自己成为navigationController的代理。这个协议类似于此前的UIViewControllerTransitioningDelegate协议。(注意: 这里的 self.navigationController.delegate = self 最好写在当前控制器的viewDidAppear方法中, 不然会导致在此push时无动画效果, 具体原因待查 = =, 如下图)

奇幻电玩城游戏下载 10

HomeViewController实现UINavigationControllerDelegate协议的具体操作如下:

奇幻电玩城游戏下载 11

UINavigationControllerDelegate代理方法

至于animator,就和此前没有任何区别了。可见,一个封装得很好的animator,不仅能在present/dismiss时使用,甚至还可以在push/pop时使用。

使用交互控制器

交互控制器和动画控制器配合使用,可以实现交互式的动画转场效果,比如可以让用户通过手势来控制页面间的导航.交互控制器允许用户在一个转场动画中前进,后退,甚至退出.

交互控制器负责给视图添加手势,并负责在用户使用某个手势时进行相应地导航操作.

自定义底部标签栏导航的转场动画

UITabBarController 有一个 id<UITabBarControllerDelegate> delegate属性,只需要让它的代理通过tabBarController: animationControllerForTransitionFromViewController: toViewController:返回某个动画效果即可.

为了给动画一个合适的方向,你可以比较两个视图控制器的索引:

- (id <UIViewControllerAnimatedTransitioning>)tabBarController:(UITabBarController *)tabBarController
            animationControllerForTransitionFromViewController:(UIViewController *)fromVC
                                              toViewController:(UIViewController *)toVC {

    NSUInteger fromVCIndex = [tabBarController.viewControllers indexOfObject:fromVC];
    NSUInteger toVCIndex = [tabBarController.viewControllers indexOfObject:toVC];

    _animationController.reverse = fromVCIndex < toVCIndex;
    return _animationController;
}

UITabBarController转场动画

同理, UITabBarController也是可以自定义转场动画的,类似前面的UINavigationController的自定义转场动画.

奇幻电玩城游戏下载 12

遵循代理

奇幻电玩城游戏下载 13

设置代理对象

所以, 接下来又是我们的animator, 你应该已经发现,animator这个词在我们这片文章中出现了N多次(这是重点!!!),先请看UITabBarControllerDelegate的代理方法实现.

奇幻电玩城游戏下载 14

UITabBarControllerDelegate代理方法

也是返回了一个自定义的实现了UIViewControllerAnimatedTransitioning协议方法的类.

模态控制器消失时的交互

UIViewControllerTransitioningDelegate 协议,也用来提供对交互式转场的支持.下面是一个结合清扫手势和翻页动画的例子:

//实例变量,通常在你的初始化方法初始化它们
CEFlipAnimationController *_animationController;
CESwipeInteractionController *_interactionController;

- (id<UIViewControllerAnimatedTransitioning>)
      animationControllerForPresentedController:(UIViewController *)presented
                           presentingController:(UIViewController *)presenting
                               sourceController:(UIViewController *)source {

    // 允许交互控制器绑定它的手势识别器.
    [_interactionController wireToViewController:presented 
                                    forOperation:CEInteractionOperationDismiss];
       _animationController.reverse = NO;
    return _animationController;
}

- (id<UIViewControllerAnimatedTransitioning>)
     animationControllerForDismissedController:(UIViewController *)dismissed {
    _animationController.reverse = YES;
    return _animationController;
}

- (id<UIViewControllerInteractiveTransitioning>)
           interactionControllerForDismissal:
                (id<UIViewControllerAnimatedTransitioning>)animator {

    // 如果有交互控制器被触发了,就直接使用它.返回nil,是为了支持用户通过点击某个按钮直接返回;此时不会触发交互控制器.
    return _interactionController.interactionInProgress
                ? _interactionController : nil;
}

使用交互控制器

交互控制器和动画控制器配合使用,可以实现交互式的动画转场效果,比如可以让用户通过手势来控制页面间的导航.交互控制器允许用户在一个转场动画中前进,后退,甚至退出.

交互控制器负责给视图添加手势,并负责在用户使用某个手势时进行相应地导航操作.

小总结

看到这里, 你应该明白了,实现了UIViewControllerAnimatedTransitioning协议方法的类(俗称animator)是整个自定义转场动画的核心.(因为,我已经在前面说了很多次了= =), 你需要用到的转场动画所涉及的对象基本都可以在这个animator中里面找到.

So, 你如果想实现炒鸡炫酷的动画,就在这个animator里面发挥你无尽的想象吧, 当然别忘记, 动画完成时记得调用[transitionContextcompleteTransition:YES]告诉代理类你已经完成了整个动画.

接下来让我们看点更加有意思的内容^_^.

出栈时的交互

UINavigationControllerDelegate 也有方法为交互式转场提供支持.一个典型的类似于上上面代码的模式:

// 实例变量,通常在你的初始化方法中初始化它们.
CEFlipAnimationController *_animationController;
CESwipeInteractionController *_interactionController;

- (id<UIViewControllerAnimatedTransitioning>)
                 navigationController:(UINavigationController *)navigationController
      animationControllerForOperation:(UINavigationControllerOperation)operation
                   fromViewController:(UIViewController *)fromVC
                     toViewController:(UIViewController *)toVC {

    // 把交互控制器绑定到你的视图控制器上.
    [_interactionController wireToViewController:toVC
                                    forOperation:CEInteractionOperationPop];

    _animationController.reverse = operation == UINavigationControllerOperationPop;

    return _animationController;
}

- (id <UIViewControllerInteractiveTransitioning>)
                         navigationController:(UINavigationController *)navigationController 
  interactionControllerForAnimationController:(id <UIViewControllerAnimatedTransitioning>)animationController {

    //如果有交互控制器被触发了,就直接使用它.返回nil,是为了支持用户通过点击某个按钮直接返回;此时不会触发交互控制器. 
    return _interactionController.interactionInProgress
                ? _interactionController : nil;
}

模态控制器消失时的交互

UIViewControllerTransitioningDelegate 协议,也用来提供对交互式转场的支持.下面是一个结合清扫手势和翻页动画的例子:

//实例变量,通常在你的初始化方法初始化它们
CEFlipAnimationController *_animationController;
CESwipeInteractionController *_interactionController;

- (id<UIViewControllerAnimatedTransitioning>)
      animationControllerForPresentedController:(UIViewController *)presented
                           presentingController:(UIViewController *)presenting
                               sourceController:(UIViewController *)source {

    // 允许交互控制器绑定它的手势识别器.
    [_interactionController wireToViewController:presented 
                                    forOperation:CEInteractionOperationDismiss];
       _animationController.reverse = NO;
    return _animationController;
}

- (id<UIViewControllerAnimatedTransitioning>)
     animationControllerForDismissedController:(UIViewController *)dismissed {
    _animationController.reverse = YES;
    return _animationController;
}

- (id<UIViewControllerInteractiveTransitioning>)
           interactionControllerForDismissal:
                (id<UIViewControllerAnimatedTransitioning>)animator {

    // 如果有交互控制器被触发了,就直接使用它.返回nil,是为了支持用户通过点击某个按钮直接返回;此时不会触发交互控制器.
    return _interactionController.interactionInProgress
                ? _interactionController : nil;
}

交互式(Interactive)转场动画

前面我们说到,设置了toViewControllertransitioningDelegate属性并且present时,UIKit会从代理处获取animator,其实这里还有一个细节:UIKit还会调用代理的interactionControllerForPresentation:方法来获取交互式控制器,如果得到了nil则执行非交互式动画,这就回到了前面的内容。

如果获取到了不是nil的对象,那么UIKit不会调用animatoranimateTransition方法,而是调用交互式控制器(还记得前面介绍动画代理的示意图么,交互式动画控制器和animator是平级关系)的startInteractiveTransition:方法。

所谓的交互式动画,通常是基于手势驱动,产生一个动画完成的百分比来控制动画效果(文章开头的gif中第二个动画效果)。整个动画不再是一次性、连贯的完成,而是在任何时候都可以改变百分比甚至取消。这需要一个实现了UIPercentDrivenInteractiveTransition协议的交互式动画控制器和animator协同工作。这看上去是一个非常复杂的任务,但UIKit已经封装了足够多细节,我们只需要在交互式动画控制器和中定义一个时间处理函数(比如处理滑动手势),然后在接收到新的事件时,计算动画完成的百分比并且调用updateInteractiveTransition来更新动画进度即可。

1.首先新建一个类,继承自UIPercentDrivenInteractiveTransition.

奇幻电玩城游戏下载 15

1) 我们写一个方法提供给外部类调用。让外部类可以看到传入手势dismiss的VC的入口。

2) 既然传入了这个需要手势dismiss的VC,我们就需要保存一下,方便在当前类的其他地方使用。所以我们新建一个属性来保存这个传入的VC.

奇幻电玩城游戏下载 16

这里你可以选一个合适的临界值

1) 你可以选择一个合适的临界值, 当到达这个临界值的时候, 来执行动画

2) 值得注意的是: 2)UIGestureRecognizerStateCancelled 的时候 要执行[self cancelInteractiveTransition], UIGestureRecognizerStateEnded 的时候[self finishInteractiveTransition].

接下里, 就改写我们的dismiss时候的动画了, 同之前的present动画化一样, 写一个动画器, 就是我们的核心, 这里就不再演示了, 道理都是一样的.

animator中的代码略去,它和非交互式动画中的animator类似。因为交互式的动画只是一种锦上添花,它必须支持非交互式的动画,比如这个例子中,点击屏幕依然出发的是非交互式的动画,只是手势滑动才会触发交互式动画。

运行看看,现在已经可以手势百分比驱动了。

完善

仔细的你一定会发现,以上代码尽管实现了手势驱动,但是点击按钮dismiss的功能无法使用了。这是因为,如果只是返回self.panInteractiveTransition, 那么点击按钮dismiss的动画将无法使用;如果只是返回nil, 那么手势滑动的效果将会无法使用。

综上,我们应该分情况分别返回。

剩下的就是一些细节问题了。比如上面提到的分情况返回手势驱动还是点击按钮、超过多少距离自动dismiss、未超过多少距离复原。

用于标签栏控制器切换时的交互

UITabBarControllerDelegate 协议也为交互式转场提供了支持.但是由于代理方法在首次初始化时不被执行,所有需要其他方式来绑定交互控制器,如KVO:

@implementation TabBarViewController {
    CEFoldAnimationController *_animationController;
    CESwipeInteractionController *_swipeInteractionController;
}

- (id)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super initWithCoder:aDecoder]) {
        self.delegate = self;

        // 创建交互/动画控制器.
        _swipeInteractionController = [CESwipeInteractionController new];
        _animationController = [CEFoldAnimationController new];
        _animationController.folds = 3;

        // 使用观察者模式监测被选中的选择器的变化情况.
        [self addObserver:self
               forKeyPath:@"selectedViewController"
                  options:NSKeyValueObservingOptionNew
                  context:nil];
    }
    return self;
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context
{
    if ([keyPath isEqualToString:@"selectedViewController"] )
    {
        // 把交互控制器绑定到视图控制器上.
        [_swipeInteractionController wireToViewController:self.selectedViewController
                                             forOperation:CEInteractionOperationTab];
    }
}



- (id <UIViewControllerAnimatedTransitioning>)tabBarController:(UITabBarController *)tabBarController
            animationControllerForTransitionFromViewController:(UIViewController *)fromVC
                                              toViewController:(UIViewController *)toVC {

    NSUInteger fromVCIndex = [tabBarController.viewControllers indexOfObject:fromVC];
    NSUInteger toVCIndex = [tabBarController.viewControllers indexOfObject:toVC];

    _animationController.reverse = fromVCIndex < toVCIndex;
    return _animationController;
}

-(id<UIViewControllerInteractiveTransitioning>)tabBarController:(UITabBarController *)tabBarController interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController
{
    return _swipeInteractionController.interactionInProgress ? _swipeInteractionController : nil;
}

@end

出栈时的交互

UINavigationControllerDelegate 也有方法为交互式转场提供支持.一个典型的类似于上上面代码的模式:

// 实例变量,通常在你的初始化方法中初始化它们.
CEFlipAnimationController *_animationController;
CESwipeInteractionController *_interactionController;

- (id<UIViewControllerAnimatedTransitioning>)
                 navigationController:(UINavigationController *)navigationController
      animationControllerForOperation:(UINavigationControllerOperation)operation
                   fromViewController:(UIViewController *)fromVC
                     toViewController:(UIViewController *)toVC {

    // 把交互控制器绑定到你的视图控制器上.
    [_interactionController wireToViewController:toVC
                                    forOperation:CEInteractionOperationPop];

    _animationController.reverse = operation == UINavigationControllerOperationPop;

    return _animationController;
}

- (id <UIViewControllerInteractiveTransitioning>)
                         navigationController:(UINavigationController *)navigationController 
  interactionControllerForAnimationController:(id <UIViewControllerAnimatedTransitioning>)animationController {

    //如果有交互控制器被触发了,就直接使用它.返回nil,是为了支持用户通过点击某个按钮直接返回;此时不会触发交互控制器. 
    return _interactionController.interactionInProgress
                ? _interactionController : nil;
}

总结

是时候来个小总结了, 其实自定义的转场的核心就是,实现了UIViewControllerAnimatedTransitioning协议方法的类(俗称animator), 你可以在里面充分发挥你的想象来做属于你自己的自定义转场动画. PS: 有兴趣的可以在AppStore下载格瓦拉电影这个App, 里面有十分多的转场动画效果.

所谓动画, 就是一些数学计算累加上前后顺序的结果, 一个再复杂的动画也可以拆分成N多小的动画模块. 同理, N多小的简单的动画累计在一起也就可以组成一个十分炫酷的动画. 开始仔细学习核心动画, 加油!

用于标签栏控制器切换时的交互

UITabBarControllerDelegate 协议也为交互式转场提供了支持.但是由于代理方法在首次初始化时不被执行,所有需要其他方式来绑定交互控制器,如KVO:

@implementation TabBarViewController {
    CEFoldAnimationController *_animationController;
    CESwipeInteractionController *_swipeInteractionController;
}

- (id)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super initWithCoder:aDecoder]) {
        self.delegate = self;

        // 创建交互/动画控制器.
        _swipeInteractionController = [CESwipeInteractionController new];
        _animationController = [CEFoldAnimationController new];
        _animationController.folds = 3;

        // 使用观察者模式监测被选中的选择器的变化情况.
        [self addObserver:self
               forKeyPath:@"selectedViewController"
                  options:NSKeyValueObservingOptionNew
                  context:nil];
    }
    return self;
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context
{
    if ([keyPath isEqualToString:@"selectedViewController"] )
    {
        // 把交互控制器绑定到视图控制器上.
        [_swipeInteractionController wireToViewController:self.selectedViewController
                                             forOperation:CEInteractionOperationTab];
    }
}



- (id <UIViewControllerAnimatedTransitioning>)tabBarController:(UITabBarController *)tabBarController
            animationControllerForTransitionFromViewController:(UIViewController *)fromVC
                                              toViewController:(UIViewController *)toVC {

    NSUInteger fromVCIndex = [tabBarController.viewControllers indexOfObject:fromVC];
    NSUInteger toVCIndex = [tabBarController.viewControllers indexOfObject:toVC];

    _animationController.reverse = fromVCIndex < toVCIndex;
    return _animationController;
}

-(id<UIViewControllerInteractiveTransitioning>)tabBarController:(UITabBarController *)tabBarController interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController
{
    return _swipeInteractionController.interactionInProgress ? _swipeInteractionController : nil;
}

@end

–自定义iOS交互式转场动画的库,ios转场动画 简介 VCTransitionsLibrary 提供了许多适用于入栈,出栈,模态等场景下控制器切换时...

本文由奇幻电玩城游戏下载发布于工程材料,转载请注明出处:iOS自定义转场动画,自定义iOS交互式转场动画的

关键词:

上一篇:ViewPager与Tab结合使用,交易与人生2
下一篇:没有了