【问题标题】:How do I do a Fade/No transition between view controllers如何在视图控制器之间进行淡入淡出/无过渡
【发布时间】:2012-06-09 14:45:48
【问题描述】:

是否可以在 Storyboard 中的视图控制器之间进行淡入和淡出转换。或者没有过渡。

如果可能,代码是什么?

【问题讨论】:

    标签: objective-c ios uistoryboardsegue


    【解决方案1】:

    如果呈现模态视图控制器,您可以指定modalTransitionStyleUIModalTransitionStyleCrossDissolve。如果在情节提要中使用 segue 执行此操作,请选择 segue 的属性检查器,并在此处指定过渡样式:

    如果以编程方式呈现视图控制器,您可以使用“Cross Dissolve”的“Transition”在情节提要中的视图控制器之间定义模态转场,然后让源视图控制器执行此转场:

    [self performSegueWithIdentifier:@"presentSegue" sender:sender];
    

    或者,如果你打电话给presentViewController

    UIViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"YourStoryboardID"];
    controller.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
    [self presentViewController:controller animated:YES completion:nil];
    

    在 iOS 7 中,Apple 提供了一项新技术,可为高度自定义的过渡提供丰富而强大的控制。欲了解更多信息,请参阅 WWDC 2013 视频Custom Transitions Using View Controllers

    但是,例如,如果您想在 iOS 7 中自定义推送和弹出动画以淡化,您可以为导航控制器指定 delegate

    - (void)viewDidLoad {
        [super viewDidLoad];
    
        self.navigationController.delegate = self;
    }
    

    然后您将实现 animationControllerForOperation 指定用于推送和弹出的动画对象:

    - (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
                                      animationControllerForOperation:(UINavigationControllerOperation)operation
                                                   fromViewController:(UIViewController*)fromVC
                                                     toViewController:(UIViewController*)toVC
    {
        if (operation == UINavigationControllerOperationPush)
            return [[PushAnimator alloc] init];
    
        if (operation == UINavigationControllerOperationPop)
            return [[PopAnimator alloc] init];
    
        return nil;
    }
    

    您显然必须实现自定义推送和弹出动画,例如:

    @interface PushAnimator : NSObject <UIViewControllerAnimatedTransitioning>
    
    @end
    
    @implementation PushAnimator
    
    - (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
    {
        return 0.5;
    }
    
    - (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
    {
        UIViewController* toViewController   = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    
        [[transitionContext containerView] addSubview:toViewController.view];
    
        toViewController.view.alpha = 0.0;
    
        [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
            toViewController.view.alpha = 1.0;
        } completion:^(BOOL finished) {
            [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
        }];
    }
    
    @end
    

    @interface PopAnimator : NSObject <UIViewControllerAnimatedTransitioning>
    
    @end
    
    @implementation PopAnimator
    
    - (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
    {
        return 0.5;
    }
    
    - (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
    {
        UIViewController* toViewController   = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
        UIViewController* fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    
        [[transitionContext containerView] insertSubview:toViewController.view belowSubview:fromViewController.view];
    
        [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
            fromViewController.view.alpha = 0.0;
        } completion:^(BOOL finished) {
            [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
        }];
    }
    
    @end
    

    自定义模态转换也有类似但略有不同的技术(尽管如果您只是做一个面部,您可能只使用上面讨论的modalTransitionStyle,除非您想要进行其他一些细微的自定义采用)。有关详细信息,请参阅上述Custom Transitions Using View Controllers

    底线,iOS 7 的自定义过渡是一种稍微复杂但非常强大的方法,可以对过渡动画提供巨大的控制。

    【讨论】:

    • 感谢您做出如此完整且可复制/粘贴的答案!
    【解决方案2】:

    为了创建自定义 Segue,创建 UIStoryboard segue 的子类。 例如:

    // MCFadeSegue.h
    #import <UIKit/UIKit.h>
    
    @interface MCFadeSegue : UIStoryboardSegue
    
    @end
    
    // MCFadeSegue.m
    #import <QuartzCore/QuartzCore.h>
    #import "MCFadeSegue.h"
    
    @implementation MCFadeSegue
    
    - (void)perform
    {
      CATransition *transition = [CATransition animation];
      transition.duration = 0.5;
      transition.type = kCATransitionFade;
    
      [[[[[self sourceViewController] view] window] layer] addAnimation:transition
          forKey:kCATransitionFade];
    
      [[self sourceViewController]
          presentViewController:[self destinationViewController]
          animated:NO completion:NULL];
    }
    
    @end
    

    然后在 MainStoryboard.storyboard 中选择 segue 并设置 Style:Custom 和 Class:MCFadeSegue。

    【讨论】:

    • 应该是@ implementation MCFadeSegue 而不是@ implementation MCFadeInSegue 与 .h 相同
    【解决方案3】:

    在 Swift 中推送/弹出 UIVIewController FadeIn/FadeOut

    class FadeInPushSegue: UIStoryboardSegue {
    
        var animated: Bool = true
    
        override func perform() {
    
            if var sourceViewController = self.sourceViewController as? UIViewController, var destinationViewController = self.destinationViewController as? UIViewController {
    
                var transition: CATransition = CATransition()
    
                transition.type = kCATransitionFade; //kCATransitionMoveIn; //, kCATransitionPush, kCATransitionReveal, kCATransitionFade
                sourceViewController.view.window?.layer.addAnimation(transition, forKey: "kCATransition")
                sourceViewController.navigationController?.pushViewController(destinationViewController, animated: false)
    
    
            }
        }
    
    }
    
    class FadeOutPopSegue: UIStoryboardSegue {
    
        override func perform() {
    
            if var sourceViewController = self.sourceViewController as? UIViewController, var destinationViewController = self.destinationViewController as? UIViewController {
    
                var transition: CATransition = CATransition()
    
                transition.duration = 0.4
                transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
                transition.type = kCATransitionFade; //kCATransitionMoveIn; //, kCATransitionPush, kCATransitionReveal, kCATransitionFade
    
                sourceViewController.view.window?.layer.addAnimation(transition, forKey: "kCATransition")
                sourceViewController.navigationController?.popViewControllerAnimated(false)
            }
        }
    
    }
    

    【讨论】:

      【解决方案4】:

      试试这个。

          let transition: CATransition = CATransition()
          transition.duration = 0.4
          transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
          transition.type = kCATransitionFade
          self.navigationController!.view.layer.addAnimation(transition, forKey: nil)
      
          let vc = self.storyboard?.instantiateViewControllerWithIdentifier("vcID") as! My_ViewController
          self.navigationController?.pushViewController(vc, animated: false)
      

      【讨论】:

      • 很好的答案。经过长时间的搜索,它对我有很大帮助。谢谢。
      【解决方案5】:

      无需创建自定义转场,我将这段代码放在一起呈现视图...

      UIViewController *nextView = [[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"YOUR_VIEW_CONTROLLER_STORYBOARD_NAME"]; nextView.modalTransitionStyle = UIModalTransitionStyleCrossDissolve; [self.navigationController presentViewController:nextView Animation:YES completion:nil]; //(对于交叉溶解,设置动画:YES。对于无过渡,设置动画:NO。)

      希望这对遇到这个问题的人有所帮助!

      【讨论】:

        【解决方案6】:

        带有可选检查的我的 Swift 版本!

            let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
            if let stView = storyboard.instantiateViewControllerWithIdentifier("STVC") as? STVC {
                stView.modalTransitionStyle = UIModalTransitionStyle.CrossDissolve
                self.navigationController?.presentViewController(stView, animated: true, completion: nil)
            }
        

        只需确保在 IB 中设置“视图控制器”的 Storyboard ID

        【讨论】:

          【解决方案7】:

          Swift 3 语法中的Push/Pop UIVIewController FadeIn/FadeOut,基于Eugene Braginetsanswer

          class FadeInPushSegue: UIStoryboardSegue {
          
              var animated: Bool = true
          
              override func perform() {
          
                  let sourceViewController = self.source
                  let destinationViewController = self.destination
          
                  let transition: CATransition = CATransition()
          
                  transition.type = kCATransitionFade; //kCATransitionMoveIn; //, kCATransitionPush, kCATransitionReveal, kCATransitionFade
                  sourceViewController.view.window?.layer.add(transition, forKey: "kCATransition")
                  sourceViewController.navigationController?.pushViewController(destinationViewController, animated: false)
          
              }
          
          }
          
          class FadeOutPopSegue: UIStoryboardSegue {
          
              override func perform() {
          
                  let sourceViewController = self.source
          
                  let transition: CATransition = CATransition()
          
                  transition.duration = 0.4
                  transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
                  transition.type = kCATransitionFade; //kCATransitionMoveIn; //, kCATransitionPush, kCATransitionReveal, kCATransitionFade
          
                  sourceViewController.view.window?.layer.add(transition, forKey: "kCATransition")
                  _ = sourceViewController.navigationController?.popViewController(animated: false)
              }
          
          }
          

          【讨论】:

            【解决方案8】:

            斯威夫特 5:

            在花费数小时寻找合适的解决方案Rob's 后,其中一个回答了我的所有需求,经过几次调整后,它是完美的。

            创建淡入淡出的视图控制器类:

            class FadeViewControllerTransition: NSObject, UIViewControllerAnimatedTransitioning {
                
                var fadeOut: Bool = false
                
                func transitionDuration(
                    using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
                    return 0.5
                }
                
                func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
                    
                    if fadeOut {
                        animateFadeOut(using: transitionContext)
                        return
                    }
                    
                    let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)!
                    transitionContext.containerView.addSubview(toViewController.view)
                    toViewController.view.alpha = 0.0
                    UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: {
                        toViewController.view.alpha = 1.0
                    }, completion: { _ in
                        transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
                    })
                }
                
                func animateFadeOut(using transitionContext: UIViewControllerContextTransitioning) {
                    
                    let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)!
                    let fromViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)!
                    transitionContext.containerView.insertSubview(toViewController.view, belowSubview: fromViewController.view)
                    UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: {
                        fromViewController.view.alpha = 0.0
                    }, completion: { _ in
                        transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
                    })
                }
            }
            

            在导航控制器的第一个视图控制器中:

            class MainViewController: UIViewController, UIViewControllerTransitioningDelegate, UINavigationControllerDelegate {
            
                private let fadeVCTransition = FadeViewControllerTransition()
                
                func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
                    fadeVCTransition.fadeOut = (operation == .pop)
                    return fadeVCTransition
                }
            

            就是这样。

            【讨论】:

            • 如何使用fadeVCTransition 变量和navigationController 函数来执行fade segue?
            【解决方案9】:

            我所做的是在 Interface Builder 中使用 Storyboard,连接了您需要移入/移出和移回的两个视图控制器(按住 ctrl 并将单击从源视图控制器拖动到目标视图控制器),并更改了 segue 属性。我使用了以下内容:

            然后我使用了以下内容:

            [self performSegueWithIdentifier:@"showMovieDetailSegue" sender:self];
            

            当你想删除它时,只需从源视图控制器中调用它:

            [self dismissViewControllerAnimated:YES completion:nil];
            

            简单快速。

            【讨论】:

              【解决方案10】:

              这让我疯了好几个小时。这些解决方案似乎都不是我想要的,我正在失去理智。最后想出了以下方法,它使用淡出/淡入转换在单个 NSWindow 内交换视图控制器。首先它执行淡出,然后在完成处理程序中,它将窗口的视图设置为新视图并执行淡入。也许有更好的方法来做到这一点,但这是我可以一起破解的最简单的方法.

              class CustomSegue : NSStoryboardSegue {
                  override func perform() {
                      guard let fromController = sourceController as? NSViewController else {
                          return;
                      }
                      guard let toController = destinationController as? NSViewController else {
                          return;
                      }
                      let animationDuration = 0.5;
                      NSAnimationContext.runAnimationGroup({
                          $0.duration = animationDuration;
                          fromController.view.animator().alphaValue = 0.0;
                      }, completionHandler: {
                          fromController.view.window?.contentViewController = toController;
                          toController.view.alphaValue = 0.0;
                          NSAnimationContext.runAnimationGroup({
                              $0.duration = animationDuration;
                              toController.view.animator().alphaValue = 1.0;
                          })
                      });
              
                  }
              }
              

              Apple 文档中缺少示例让我想绞尽脑汁,Objective C 和 Swift 的混合无处不在……呸!

              【讨论】:

                【解决方案11】:

                在没有过渡的情况下呈现:

                • 在情节提要中选择您的转场
                • 在属性检查器中取消选中“动画”

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2015-11-22
                  • 2012-05-20
                  • 2012-02-04
                  • 2012-07-26
                  相关资源
                  最近更新 更多