简体   繁体   English

如何在视图控制器之间进行淡入淡出/无过渡

[英]How do I do a Fade/No transition between view controllers

Is it possible to do a fade in and fade out transition between View Controllers in Storyboard.是否可以在 Storyboard 中的视图控制器之间进行淡入和淡出过渡。 Or without transition.或者没有过渡。

If it's possible, what's the code for it?如果可能,它的代码是什么?

If presenting a modal view controller, you can specify a modalTransitionStyle of UIModalTransitionStyleCrossDissolve .如果呈现一个模态视图控制器,您可以指定modalTransitionStyleUIModalTransitionStyleCrossDissolve If doing this with a segue in your storyboard, select the attributes inspector for the segue, and specify the transition style there:如果在故事板中使用 segue 执行此操作,请选择 segue 的属性检查器,并在那里指定过渡样式:

在此处输入图片说明

If presenting the view controller programmatically, you can define your modal segue between the view controllers in your storyboard with a "Transition" of "Cross Dissolve" and then have the source view controller perform this segue:如果以编程方式呈现视图控制器,您可以使用“Cross Dissolve”的“Transition”在故事板中的视图控制器之间定义模态转场,然后让源视图控制器执行此转场:

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

Or, if you are calling presentViewController :或者,如果您正在调用presentViewController

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

In iOS 7, Apple has provided a new technology that provides a rich and robust control for highly customized transitions.在 iOS 7 中,Apple 提供了一项新技术,可为高度自定义的过渡提供丰富而强大的控件。 For more information, refer to WWDC 2013 video Custom Transitions Using View Controllers .有关更多信息,请参阅 WWDC 2013 视频使用视图控制器自定义过渡

But, for instance, if you want to customize the push and pop animations in iOS 7 to fade, you would specify a delegate for the navigation controller但是,例如,如果您想自定义 iOS 7 中的推送和弹出动画以淡入淡出,您需要为导航控制器指定一个delegate

- (void)viewDidLoad {
    [super viewDidLoad];

    self.navigationController.delegate = self;
}

You would then implement animationControllerForOperation that specified the animator objects for pushing and popping:然后,您将实现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;
}

You'd obviously have to implement your custom push and pop animators, such as:您显然必须实现自定义推送和弹出动画,例如:

@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

And

@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

There is a similar, but slightly different technique for customizing modal transitions, too (though if you were just doing a face, you'd probably just use the modalTransitionStyle discussed above unless there was some other subtle customization you wanted to employ).也有一种类似但略有不同的自定义模态转换技术(尽管如果您只是在做一个人脸,您可能只使用modalTransitionStyle讨论的modalTransitionStyle ,除非您想使用其他一些微妙的自定义)。 See the aforementioned Custom Transitions Using View Controllers for more information.有关更多信息,请参阅上述使用视图控制器的自定义过渡

Bottom line, custom transitions for iOS 7 are a slightly complicated, but very robust way to provide tremendous control over the animations for transitions.最重要的是,iOS 7 的自定义过渡是一种稍微复杂但非常强大的方式,可以为过渡动画提供巨大的控制。

For creating Custom Segue create subclass of UIStoryboard segue.要创建自定义转场,请创建 UIStoryboard 转场的子类。 For example:例如:

// 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

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

Push/Pop UIVIewController FadeIn/FadeOut in Swift Swift 中的推送/弹出 UIVIewController 淡入/淡出

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)
        }
    }

}

Try this one.试试这个。

    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)

Without needing to create a custom segue, I put together this code to present the view...无需创建自定义转场,我将这段代码放在一起来呈现视图......

UIViewController *nextView = [[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"YOUR_VIEW_CONTROLLER_STORYBOARD_NAME"];

nextView.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;

[self.navigationController presentViewController:nextView animated:YES completion:nil];
// (For a cross dissolve, set animated:YES.  For no transition, set animated:NO.)

Hope this helps anyone who comes across this question!希望这可以帮助遇到这个问题的任何人!

My Swift Version with optional checking offcourse!我的 Swift 版本带有可选的检查offcourse!

    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)
    }

Just make sure to set the Storyboard ID of the "View controller" in IB只需确保在 IB 中设置“视图控制器”的 Storyboard ID

Push/Pop UIVIewController FadeIn/FadeOut in Swift 3 syntax, based on Eugene Braginets 's answer Push/Pop UIVIewController FadeIn/FadeOut in Swift 3语法,基于Eugene Braginets回答

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)
    }

}

What I did was to use Storyboard in Interface Builder, connected the two viewcontroller you need to move to /from and back (hold ctrl and drag click from the origin viewcontroller to destination viewcontroller), and changed the segue properties.我所做的是在Interface Builder中使用Storyboard,连接您需要移动到/从和返回的两个视图控制器(按住ctrl并将单击从原始视图控制器拖动到目标视图控制器),并更改segue属性。 I used the following:我使用了以下内容:

在此处输入图片说明

I then used the following:然后我使用了以下内容:

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

when you want to remove it, just call this from the origin viewcontroller:当你想删除它时,只需从原始视图控制器调用它:

[self dismissViewControllerAnimated:YES completion:nil];

Simple and very quick.简单而且非常快。

This drove me absolutely nuts for several hours.这让我彻底疯了几个小时。 None of these solutions seemed to be what I wanted, and I was losing my mind.这些解决方案似乎都不是我想要的,我正在失去理智。 Finally came up with the following, which swaps view controllers within a single NSWindow using a fade out/fade in transition.最后提出了以下内容,它使用淡出/淡入过渡在单个 NSWindow 中交换视图控制器。 First it performs a fade out, then, in the completion handler, it sets the view for the window to the new view and performs a fade in. Maybe there's a better way to do this, but this is the simplest way I could hack together.首先它执行淡出,然后在完成处理程序中,它将窗口的视图设置为新视图并执行淡入。也许有更好的方法来做到这一点,但这是我可以一起破解的最简单的方法.

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;
            })
        });

    }
}

The lack of examples in Apple documentation makes me want to tear my brain out, and the mix of Objective C and Swift everywhere is just... bah! Apple 文档中缺少示例让我想绞尽脑汁,Objective C 和 Swift 的混合无处不在,简直是……呸!

Swift 5:斯威夫特 5:

After spending hours on finding the right solution Rob's one answered all of my needs, after a few adjustments it was perfect.在花了几个小时寻找正确的解决方案后, Rob 的一个解决了我的所有需求,经过一些调整后,它是完美的。

Create the fade View Controller class:创建淡入淡出视图控制器类:

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)
        })
    }
}

In your Navigation Controller's first View Controller:在导航控制器的第一个视图控制器中:

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
    }

And that's it.就是这样。

To present WITHOUT Transition:无过渡呈现:

  • Select your segue in the Storyboard在故事板中选择您的转场
  • Uncheck "Animates" in the Attributes Inspector在属性检查器中取消选中“动画”

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM