【问题标题】:Create an animation for UIView to coincide with UINavigationController push/pop为 UIView 创建动画以与 UINavigationController 推送/弹出一致
【发布时间】:2014-08-14 00:04:15
【问题描述】:

我的应用程序的初始 ViewController 有 2 个容器视图:第一个包含一个 ViewController,里面是一个 UINavigationController,它控制应用程序的主要内容。初始 VC 的第二个容器视图是一个带有 UILabel 的小条,位于导航栏所在位置的正下方。

主内容VC的导航栈的初始VC隐藏了导航栏。所有后续 VC 将显示导航栏以及初始 VC 的第二个容器视图。当应用程序离开导航堆栈的初始 VC 时,我想在第二个容器 VC 中设置动画。

我的问题是,我需要创建什么动画来匹配导航控制器在将 VC 推入/弹出导航堆栈时执行的动画?我目前正在使用:

[UIView animateWithDuration:0.27f delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
    self.playerCardVC.frame = secondFrame;
} completion:nil];

但是当导航栏动画进入视图时,它并不完全匹配。任何想法/想法将不胜感激。

更新:

我一直在网上搜索此问题的答案,并尝试调整我最初问题中发布的动画,但似乎无法完美匹配导航栏的动画效果。任何正确方向的 cmets 或点将不胜感激。

【问题讨论】:

    标签: ios objective-c uinavigationcontroller uicontainerview


    【解决方案1】:

    从上面的描述很难理解你的视图层次和导航设计,也许你可以发布一些截图或草图?

    您可以覆盖 UINavigationController 的标准水平推送/弹出动画。您可以通过定义自定义 UINavigationControllerDelegate 对象和其他一些东西来做到这一点。见下文。

    像这样设置你的 navController 和 navControllerDelegate:

    UINavigationController *navigationController = [[UINavigationController alloc] init];
    self.navigationControllerDelegate = [[NavigationControllerDelegate alloc] init];
    navigationController.delegate = self.navigationControllerDelegate;
    

    NavigationControllerDelegate 类如下所示:

    @interface NavigationControllerDelegate : NSObject <UINavigationControllerDelegate>
    
    @end
    
    
    #import "NavigationControllerDelegate.h"
    #import "CrossFadePushAnimator.h"
    #import "CrossFadePopAnimator.h"
    
    @interface NavigationControllerDelegate ()
    
    @property (nonatomic, strong) CrossFadePushAnimator* pushAnimator;
    @property (nonatomic, strong) CrossFadePopAnimator* popAnimator;
    
    @end
    
    @implementation NavigationControllerDelegate
    
    - (id)init
    {
        self = [super init];
        if (self)
        {
            self.pushAnimator = [CrossFadePushAnimator new];
            self.popAnimator = [CrossFadePopAnimator new];
        }
    
        return self;
    }
    
    - (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC
        {
        if (operation == UINavigationControllerOperationPop)
        {
            return self.popAnimator;
        }
        else if (operation == UINavigationControllerOperationPush)
        {
            return self.pushAnimator;
        }
    
        return nil;
    }
    
    - (id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController
    {
        return nil;
    }
    

    pushAnimator 看起来像这样:

    @interface CrossFadePushAnimator ()
    
    @property (nonatomic, strong) id<UIViewControllerContextTransitioning> transitionContext;
    
    @end
    
    @implementation CrossFadePushAnimator
    
    - (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
    {
        return AnimationDuration;
    }
    
    - (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
    {
        UIViewController* toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    //    UIViewController* fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    
        [[transitionContext containerView] addSubview:toViewController.view];
        toViewController.view.alpha = 1.0f;
    
        // We are using CAAnimation instead of UIView animation because we need the UIToolbar blur layer to animate
        CABasicAnimation *fade = [CABasicAnimation animationWithKeyPath:@"opacity"];
        fade.fromValue = @0;
        fade.toValue = @1;
        fade.duration = [self transitionDuration:transitionContext];
        fade.removedOnCompletion = YES;
        fade.delegate = self;
    
        self.transitionContext = transitionContext;
        [toViewController.view.layer addAnimation:fade forKey:AnimationKey];
    }
    
    - (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag
    {
        [self.transitionContext completeTransition:![self.transitionContext transitionWasCancelled]];
        self.transitionContext = nil;
    }
    

    popAnimator 看起来有点像 pushAnimator。

    希望这会有所帮助!

    【讨论】:

      【解决方案2】:

      从上面的描述很难理解你的视图层次和导航设计,也许你可以发布一些截图或草图?

      您可以覆盖 UINavigationController 的标准水平推送/弹出动画。您可以通过定义自定义 UINavigationControllerDelegate 对象和其他一些东西来做到这一点。见下文。

      像这样设置你的 navController 和 navControllerDelegate:

      UINavigationController *navigationController = [[UINavigationController alloc] init];
      self.navigationControllerDelegate = [[NavigationControllerDelegate alloc] init];
      navigationController.delegate = self.navigationControllerDelegate;
      

      NavigationControllerDelegate 类如下所示:

      @interface NavigationControllerDelegate : NSObject <UINavigationControllerDelegate>
      
      @end
      
      
      #import "NavigationControllerDelegate.h"
      #import "CrossFadePushAnimator.h"
      #import "CrossFadePopAnimator.h"
      
      @interface NavigationControllerDelegate ()
      
      @property (nonatomic, strong) CrossFadePushAnimator* pushAnimator;
      @property (nonatomic, strong) CrossFadePopAnimator* popAnimator;
      
      @end
      
      @implementation NavigationControllerDelegate
      
      - (id)init
      {
          self = [super init];
          if (self)
          {
              self.pushAnimator = [CrossFadePushAnimator new];
              self.popAnimator = [CrossFadePopAnimator new];
          }
      
          return self;
      }
      
      - (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC
          {
          if (operation == UINavigationControllerOperationPop)
          {
              return self.popAnimator;
          }
          else if (operation == UINavigationControllerOperationPush)
          {
              return self.pushAnimator;
          }
      
          return nil;
      }
      
      - (id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController
      {
          return nil;
      }
      

      pushAnimator 看起来像这样:

      @interface CrossFadePushAnimator ()
      
      @property (nonatomic, strong) id<UIViewControllerContextTransitioning> transitionContext;
      
      @end
      
      @implementation CrossFadePushAnimator
      
      - (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
      {
          return AnimationDuration;
      }
      
      - (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
      {
          UIViewController* toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
      
          [[transitionContext containerView] addSubview:toViewController.view];
          toViewController.view.alpha = 1.0f;
      
          // I'm using CABasicAnimation here for a specific reason, but you could also use the animation method you use above.
          CABasicAnimation *fade = [CABasicAnimation animationWithKeyPath:@"opacity"];
          fade.fromValue = @0;
          fade.toValue = @1;
          fade.duration = [self transitionDuration:transitionContext];
          fade.removedOnCompletion = YES;
          fade.delegate = self;
      
          self.transitionContext = transitionContext;
          [toViewController.view.layer addAnimation:fade forKey:AnimationKey];
      }
      
      - (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag
      {
          [self.transitionContext completeTransition:![self.transitionContext transitionWasCancelled]];
          self.transitionContext = nil;
      }
      

      popAnimator 看起来有点像 pushAnimator。

      希望这会有所帮助!

      【讨论】:

        猜你喜欢
        • 2011-08-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多