ios 如何将 UIViewControllerAnimatedTransitioning 与 UINavigationController 一起使用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22884111/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 23:55:09  来源:igfitidea点击:

How to use UIViewControllerAnimatedTransitioning with UINavigationController?

ioscocoa-touchios7xamarin.ios

提问by Krumelur

How can I get custom transitions (iOS7) when pushing a view controller onto UINavigationController? I tried setting the TransitioningDelegateboth in the UINavigationControllerand also on the controller I'm pushing The methods never get called.

将视图控制器推到 上时如何获得自定义转换(iOS7)UINavigationController?我尝试TransitioningDelegateUINavigationController我正在推动的控制器中和控制器上设置方法永远不会被调用。

All examples I find use custom transitions when presenting modally.

我发现的所有示例在模态呈现时都使用自定义转换。

回答by Jon

@rounak has the right idea, but sometimes it helps to have code ready without having to download from github.

@rounak 的想法是正确的,但有时无需从 github 下载就可以准备好代码。

Here are the steps that I took:

以下是我采取的步骤:

  1. Make your FromViewController.m conform to UINavigationControllerDelegate. Other sample code out there tells you to conform to UIViewControllerTransitioningDelegate, but that's only if you're presentingthe ToViewController.

    @interface ViewController : UIViewController

  2. Return your custom transition animator object in the delegate callback method in FromViewController:

    - (id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
                                   animationControllerForOperation:(UINavigationControllerOperation)operation
                                                fromViewController:(UIViewController *)fromVC
                                                  toViewController:(UIViewController *)toVC {
        TransitionAnimator *animator = [TransitionAnimator new];
        animator.presenting = (operation == UINavigationControllerOperationPush);
        return animator;
    }
    
  3. Create your custom animator class and paste these sample methods:

    - (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext {
        return 0.5f;
        }
    
    - (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext     {
    // Grab the from and to view controllers from the context
    UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    
    // Set our ending frame. We'll modify this later if we have to
    CGRect endFrame = CGRectMake(80, 280, 160, 100);
    
    if (self.presenting) {
        fromViewController.view.userInteractionEnabled = NO;
    
        [transitionContext.containerView addSubview:fromViewController.view];
        [transitionContext.containerView addSubview:toViewController.view];
    
        CGRect startFrame = endFrame;
        startFrame.origin.x += 320;
    
        toViewController.view.frame = startFrame;
    
        [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
            fromViewController.view.tintAdjustmentMode = UIViewTintAdjustmentModeDimmed;
            toViewController.view.frame = endFrame;
        } completion:^(BOOL finished) {
            [transitionContext completeTransition:YES];
        }];
    }
    else {
        toViewController.view.userInteractionEnabled = YES;
    
        [transitionContext.containerView addSubview:toViewController.view];
        [transitionContext.containerView addSubview:fromViewController.view];
    
        endFrame.origin.x += 320;
    
        [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
            toViewController.view.tintAdjustmentMode = UIViewTintAdjustmentModeAutomatic;
            fromViewController.view.frame = endFrame;
        } completion:^(BOOL finished) {
            [transitionContext completeTransition:YES];
        }];
    }
    }
    
  1. 使您的 FromViewController.m 符合UINavigationControllerDelegate. 那里的其他示例代码告诉您符合UIViewControllerTransitioningDelegate,但这仅当您呈现ToViewController 时。

    @interface ViewController : UIViewController

  2. 在 FromViewController 的委托回调方法中返回您的自定义过渡动画对象:

    - (id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
                                   animationControllerForOperation:(UINavigationControllerOperation)operation
                                                fromViewController:(UIViewController *)fromVC
                                                  toViewController:(UIViewController *)toVC {
        TransitionAnimator *animator = [TransitionAnimator new];
        animator.presenting = (operation == UINavigationControllerOperationPush);
        return animator;
    }
    
  3. 创建您的自定义动画师类并粘贴这些示例方法:

    - (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext {
        return 0.5f;
        }
    
    - (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext     {
    // Grab the from and to view controllers from the context
    UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    
    // Set our ending frame. We'll modify this later if we have to
    CGRect endFrame = CGRectMake(80, 280, 160, 100);
    
    if (self.presenting) {
        fromViewController.view.userInteractionEnabled = NO;
    
        [transitionContext.containerView addSubview:fromViewController.view];
        [transitionContext.containerView addSubview:toViewController.view];
    
        CGRect startFrame = endFrame;
        startFrame.origin.x += 320;
    
        toViewController.view.frame = startFrame;
    
        [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
            fromViewController.view.tintAdjustmentMode = UIViewTintAdjustmentModeDimmed;
            toViewController.view.frame = endFrame;
        } completion:^(BOOL finished) {
            [transitionContext completeTransition:YES];
        }];
    }
    else {
        toViewController.view.userInteractionEnabled = YES;
    
        [transitionContext.containerView addSubview:toViewController.view];
        [transitionContext.containerView addSubview:fromViewController.view];
    
        endFrame.origin.x += 320;
    
        [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
            toViewController.view.tintAdjustmentMode = UIViewTintAdjustmentModeAutomatic;
            fromViewController.view.frame = endFrame;
        } completion:^(BOOL finished) {
            [transitionContext completeTransition:YES];
        }];
    }
    }
    

Essentially, the animator is the object doing the heavy lifting. Of course, you can make your UINavigationControllerDelegate be a separate object, but that depends on how your architect your app.

本质上,动画师是承担重任的对象。当然,您可以让 UINavigationControllerDelegate 成为一个单独的对象,但这取决于您的应用程序架构。

回答by rounak

objc.io's post on view controller transitions are specifically for pushing and popping view controllers. http://objc.io/issue-5/view-controller-transitions.html

objc.io 关于视图控制器转换的帖子专门用于推送和弹出视图控制器。http://objc.io/issue-5/view-controller-transitions.html

I've done this animation (http://i.imgur.com/1qEyMu3.gif) solely based on the objc.io post.

我已经完全基于 objc.io 帖子完成了这个动画 ( http://i.imgur.com/1qEyMu3.gif)。

In short you have to have a class(es) implementing UINavigationControllerDelegate, and UIViewControllerAnimatedTransitioningwith the required methods for returning the correct animator, and performing the animations.

简而言之,您必须有一个类来实现UINavigationControllerDelegate,并UIViewControllerAnimatedTransitioning具有返回正确动画师和执行动画所需的方法。

回答by Patrik Vaberer

You can look at my demo project which demonstrates using custom transitions in UINavigationController. Look at https://github.com/Vaberer/BlurTransition.

您可以查看我的演示项目,该项目演示了在UINavigationController. 查看https://github.com/Vaberer/BlurTransition

回答by Pulsar

EDIT: Just realised this might not answer your question. But it is an alternative.

编辑:刚刚意识到这可能无法回答您的问题。但它是一种替代方法。

If you're using a storyboard you can do a custom transition by creating a custom segue. In the attributes inspector change the segue class name to your custom transition class e.g. MySegue. Then create the MySegueclass and implement the -(void)performmethod to perform your transition.

如果您使用的是故事板,您可以通过创建自定义转场来进行自定义转换。在属性检查器中,将 segue 类名称更改为您的自定义过渡类,例如MySegue. 然后创建MySegue类并实现-(void)perform方法来执行您的转换。

- (void) perform{
      UIViewController *source = self.sourceViewController;
      UIViewController *destination = self.destinationViewController;
      [UIView transitionFromView:source.view
                          toView:destination.view
                        duration:0.50f
                         options:UIViewAnimationOptionTransitionFlipFromTop
                      completion:nil];
}