VCTransitionsLibrary 1.5.0

VCTransitionsLibrary 1.5.0

测试已测试
Lang语言 Obj-CObjective C
许可 MIT
发布最近发布2014年12月

Colin Eberhardt维护。



  • Colin Eberhardt

视图控制器过渡库

自iOS 7以来,您可以在各种情况下(推送、弹出、模态等)轻松创建自定义视图控制器过渡。该项目提供了一个可以在项目中直接使用的自定义动画库。它还包含多个“交互控制器”,可以与任何自定义动画一起使用,以便使过渡具有交互性。

库中目前包含以下动画,可以通过滑动或捏合手势使其具有交互性。

翻转 折叠 淡入淡出 爆炸
翻转 卡片 NatGeo 门户
立方体 平移

内容

自定义过渡的简要介绍

以下提供了一些简要的概念介绍,更详细的介绍,我强烈建议阅读iOS 7 By Tutorials的第3章(就是我写的!) -听说其他15章也相当不错;(-”)

涉及自定义过渡的两个关键类

  • 动画控制器 - 这个类负责执行自定义过渡。当指定应使用自定义过渡时,您提供了一个动画控制器。该类执行所需的动画,然后通知框架完成。
  • 交互控制器 - 这个类负责管理交互式过渡 - 这些是通过手势控制的过渡,允许用户滑动、捏合或执行其他操作在视图控制器之间进行导航。重要的是,交互控制器允许过渡被取消,即用户可以开始导航,改变主意,然后撤销它!

注意:动画和交互控制器完全独立,这意味着你可以将任何交互控制器与任何动画控制器连接起来——这真是太棒了。

将自定义转换添加到您的项目中

本节简要概述了将自定义视图控制器转换添加到项目中所需的步骤。您还可以查看示例应用的代码(在TransitionsDemo文件夹中)以供参考。如果您已经了解iOS 7自定义视图控制器转换的工作原理,则可以跳过本节!

获取代码

您可以通过几种方式将此库中的转换集成到代码中

  1. Cocoapods - 在您的Podfile中简单添加对VCTransitionsLibrary的引用。
  2. 手动文件复制 - 如果您不使用Cocoapods,您可以简单地复制所需的文件到您的项目中。在AnimationControllersInteractionControllers文件夹中包含所有所需的代码。

使用动画控制器

AnimationControllers文件夹包含多个动画控制器,它们提供自定义转换,可以按以下方式集成到您的项目中

自定义呈现/消失转换

使用UIViewControllerTransitioningDelegate协议来提供呈现/消失转换的动画控制器。当一个视图控制器被呈现或消失时,所呈现或消失的视图控制器的transitioningDelegate属性被用来提供这个代理。在响应呈现时的animationControllerForPresentedController: presentingController: sourceController:消息中返回一个动画控制器,在消失时返回animationControllerForDismissedController:

自定义导航控制器转换

UINavigationControllerDelegate协议中包含可用来提供动画控制器的方法。简单地返回一个动画控制器来响应navigationController: animationControllerForOperation: fromViewController: toViewController:消息。

注意这个消息有一个‘operation’参数,它可以让你为推送和弹出操作返回不同的动画。此库中的所有动画控制器都是CEReversibleAnimationController的子类,这允许你反向播放动画。这通常与导航控制器一起使用,如下所示

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

    // reverse the animation for 'pop' transitions
    _animationController.reverse = operation == UINavigationControllerOperationPop;

    return _animationController;
}

自定义标签栏控制器转换

UITabBarControllerDelegate协议中包含可用来提供动画控制器的方法。简单地返回一个动画控制器来响应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;
}

使用交互控制器

交互控制器与动画控制器协同工作,使得转换成为可交互的,即允许用户使用手势控制转换。这种交互性使用户可以向前移动、向后移动,甚至取消转换。

交互控制器负责向视图添加手势识别器,并在用户手势触发时启动导航。

交互式消失过渡效果

用于提供动画控制器的UIViewControllerTransitioningDelegate协议也用于提供交互控制器。以下是一个示例实现,它使用滑动交互和翻页动画

// instance variables, typically instantiated in your init method
CEFlipAnimationController *_animationController;
CESwipeInteractionController *_interactionController;

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

    // allow the interaction controller to wire-up its gesture recognisers
    [_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 {

    // provide the interaction controller, if an interactive transition is in progress
    return _interactionController.interactionInProgress
                ? _interactionController : nil;
}

请注意,在上面的代码中检查了交互控制器的interactionInProgress属性。这是因为您可能还希望允许用户通过按钮以及通过交互来删除视图控制器。另外,您必须告诉交互控制器它应该执行的操作(例如:推送、取消)。

交互式推送过渡效果

UINavigationControllerDelegate协议还有一个返回交互控制器的方法。以下是一个通常的实现,它与上面的模式相同

// instance variables, typically instantiated in your init method
CEFlipAnimationController *_animationController;
CESwipeInteractionController *_interactionController;

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

    // wire the interaction controller to the to- view controller
    [_interactionController wireToViewController:toVC
                                    forOperation:CEInteractionOperationPop];

    _animationController.reverse = operation == UINavigationControllerOperationPop;

    return _animationController.reverse;
}

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

    // provide the interaction controller, if an interactive transition is in progress
    return _interactionController.interactionInProgress
                ? _interactionController : nil;
}

交互式标签控制器的过渡效果

UITabBarControllerDelegate协议也有一个返回交互控制器的方法。与上面的导航控制器示例一样,交互控制器需要将其手势识别器添加到标签控制器导航之间的视图控制器中。不幸的是,当第一个视图控制器呈现时,标签代理方法不会触发,所以我选择了使用键值观察的稍显混乱的实现。

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

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

        // create the interaction / animation controllers
        _swipeInteractionController = [CESwipeInteractionController new];
        _animationController = [CEFoldAnimationController new];
        _animationController.folds = 3;

        // observe changes in the currently presented view controller
        [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"] )
    {
        // wire the interaction controller to the view controller
        [_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

过渡库

以下是对各种过渡效果的图形说明。所有动画控制器都有一个duration属性来配置动画时长。

卷动动画 - CEFoldAnimationController

使用纸张折叠风格的过渡在两个视图控制器之间进行动画。您可以通过folds属性配置折叠的次数。

翻转动画 - CEFlipAnimationController

使用翻页过渡在两个视图控制器之间进行动画。

NatGeo动画 - CENatGeoAnimationController

使用受启发于国家地理城市指南的过渡在两个视图控制器之间进行动画。它是通过MHNatGeoViewControllerTransition到iOS7 API进行适配的。

翻转动画 - CETurnAnimationController

通过执行3D翻转以显示目标视图背面来在两个视图控制器之间进行动画。翻转动画有一个flipDirection属性指定翻转方向。

交叉渐变动画 - CECrossfadeAnimationController

通过简单的交叉渐变在两个视图控制器之间进行动画。

爆炸动画 - CEExplodeAnimationController

通过将来源视图控制器切成许多小片,然后随机旋转和缩小它们,在两个视图控制器之间进行动画。

卡片动画 - CECardsAnimationController

给人一种视图控制器推动另一个视图控制器到后面的印象。它看起来比这些静态截图酷多了!

(由Tope - AppDesignVault提供)

门户动画 - CEPortalAnimationController

在中间部分露出底下的视图控制器。

(由FreddyF提供)

立方体动画 - CECubeAnimationController

这种过渡效果看起来像是在旋转立方体的表面。

(由Andrés Brun提供)