为了账号安全,请及时绑定邮箱和手机立即绑定

导航控制器自定义过渡动画

导航控制器自定义过渡动画

iOS
catspeake 2019-12-09 14:15:35
我一直在遵循一些教程来创建自定义动画,同时从一个视图过渡到另一个视图。我的测试项目从这里使用自定义segue 可以正常工作,但是有人告诉我,不再鼓励在自定义segue中进行自定义动画,我应该使用UIViewControllerAnimatedTransitioning。我遵循了一些使用此协议的教程,但所有教程都是关于模式表示的(例如本教程)。我想做的是在导航控制器树中进行推送选择,但是当我尝试对显示(推送)选择执行相同的操作时,它将不再起作用。请告诉我在导航控制器中进行从一个视图到另一个视图的自定义过渡动画的正确方法。而且无论如何,我可以对所有过渡动画使用一种方法吗?如果有一天我想做同样的动画,但是最终不得不重复两次代码以进行模态与控制器转换,那将很尴尬。
查看完整描述

3 回答

?
幕布斯7119047

TA贡献1794条经验 获得超8个赞

要使用导航控制器(UINavigationController)进行自定义转换,您应该:


定义您的视图控制器以符合UINavigationControllerDelegate协议。例如,您可以在视图控制器的.m文件中具有私有类扩展名,该扩展名指定对此协议的符合性:


@interface ViewController () <UINavigationControllerDelegate>


@end

确保您确实将视图控制器指定为导航控制器的委托:


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


@interface PopAnimator : 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


@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

确实会出现淡入淡出的过渡,但是您应该随心所欲地自定义动画。


如果您想处理交互式手势(例如,从左向右滑动本机滑动之类的东西),则必须实现一个交互控制器:


定义交互控制器(符合的对象UIViewControllerInteractiveTransitioning)的属性:


@property (nonatomic, strong) UIPercentDrivenInteractiveTransition *interactionController;

这UIPercentDrivenInteractiveTransition是一个不错的对象,它会根据手势的完成程度来繁琐地更新自定义动画。


将手势识别器添加到视图。在这里,我只是实现左手势识别器来模拟弹出:


UIScreenEdgePanGestureRecognizer *edge = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeFromLeftEdge:)];

edge.edges = UIRectEdgeLeft;

[view addGestureRecognizer:edge];

实现手势识别处理程序:


/** Handle swipe from left edge

 *

 * This is the "action" selector that is called when a left screen edge gesture recognizer starts.

 *

 * This will instantiate a UIPercentDrivenInteractiveTransition when the gesture starts,

 * update it as the gesture is "changed", and will finish and release it when the gesture

 * ends.

 *

 * @param   gesture       The screen edge pan gesture recognizer.

 */


- (void)handleSwipeFromLeftEdge:(UIScreenEdgePanGestureRecognizer *)gesture {

    CGPoint translate = [gesture translationInView:gesture.view];

    CGFloat percent   = translate.x / gesture.view.bounds.size.width;


    if (gesture.state == UIGestureRecognizerStateBegan) {

        self.interactionController = [[UIPercentDrivenInteractiveTransition alloc] init];

        [self popViewControllerAnimated:TRUE];

    } else if (gesture.state == UIGestureRecognizerStateChanged) {

        [self.interactionController updateInteractiveTransition:percent];

    } else if (gesture.state == UIGestureRecognizerStateEnded) {

        CGPoint velocity = [gesture velocityInView:gesture.view];

        if (percent > 0.5 || velocity.x > 0) {

            [self.interactionController finishInteractiveTransition];

        } else {

            [self.interactionController cancelInteractiveTransition];

        }

        self.interactionController = nil;

    }

}

在导航控制器委托中,还必须实现interactionControllerForAnimationController委托方法


- (id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController

                         interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController {

    return self.interactionController;

}

如果您在Google上搜索“ UINavigationController自定义过渡教程”,那么您将获得很多成功。或参阅WWDC 2013 Custom Transitions视频。


查看完整回答
反对 回复 2019-12-09
?
猛跑小猪

TA贡献1858条经验 获得超8个赞

您可能想在之前添加以下代码 addSubview


  toViewController.view.frame = [transitionContext finalFrameForViewController:toViewController];

来自另一个问题,在iOS 9上使用navigationcontroller为推送动画进行自定义转换


从Apple的finalFrameForViewController文档中:


返回指定视图控制器视图的结束帧矩形。


此方法返回的矩形表示过渡结束时相应视图的大小。对于演示过程中涉及的视图,此方法返回的值可能是CGRectZero,但也可能是有效的框架矩形。


查看完整回答
反对 回复 2019-12-09
  • 3 回答
  • 0 关注
  • 492 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信