zoukankan      html  css  js  c++  java
  • iOS 利用UIPresentationController自定义转场动画

    1. 系统默认modal出来的动画效果默认是从屏幕底部爬出来的

    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

        secondVC *second = [[secondVC alloc] init];

      [self presentViewController:second animated:YES completion:nil];

    }

    2. 想自定义转场动画,首先设置 展示样式过渡代理

        secondVC *second = [[secondVC alloc] init];

        second.modalPresentationStyle = UIModalPresentationCustom;

        second.transitioningDelegate = self;

        [self presentViewController:second animated:YES completion:nil];

    3.实现过渡代理方法,告诉程序" 哪个对象管理控制器的展示 "

    - (UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented presentingViewController:(UIViewController *)presenting sourceViewController:(UIViewController *)source

    {

        return [[MYPresentationController alloc]initWithPresentedViewController:presented presentingViewController:presenting];

    }

    4.自定义UIPresentationController

    // MYPresentationController.h

    @interface MYPresentationController : UIPresentationController

    @end

    // MYPresentationController.m

    #import "MYPresentationController.h"

    @implementation MYPresentationController

    - (CGRect)frameOfPresentedViewInContainerView

    {  

      return CGRectMake(100, 100, 150, 300); //设置modal出来控制器的frame

    }

    // 下面这几个方法,监听Modal控制器时的各种状态

    - (void)presentationTransitionWillBegin

    {

        NSLog(@"presentationTransitionWillBegin"); 

    }

    - (void)presentationTransitionDidEnd:(BOOL)completed

    {

        NSLog(@"presentationTransitionDidEnd");

    }

    - (void)dismissalTransitionWillBegin

    {

        NSLog(@"presentationTransitionDidEnd");

    }

    - (void)dismissalTransitionDidEnd:(BOOL)completed

    {

        NSLog(@"dismissalTransitionDidEnd");

    }

    @end

    5. 到了第4步,也只是做到了自定义展示,可以监听展示的过程,可以设置展示的frame.

      要想实现自定义转场动画,可以考虑设置second.modalTransitionStyle,但是没有UIModalTransitionStyleCustom,是因为

        只要设置了UIModalPresentationCustom,也就相当于设置了"UIModalTransitionStyleCustom",要想实现自定义转场动画,只要实现相应的代理方法即可

        secondVC *second = [[secondVC alloc] init];

        second.modalPresentationStyle = UIModalPresentationCustom;

        second.transitioningDelegate = self;

      second.modalTransitionStyle = UIModalTransitionStyleCoverVertical; // 要实现自定义转场动画,不是在这里设置

        [self presentViewController:second animated:YES completion:nil];

    #pragma mark - 自定义转场动画的代理方法,两个,分别控制显示和消失

    - (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source

    {

        return self; // 简单处理,返回self,只要self遵守<UIViewControllerAnimatedTransitioning>协议

    }

    - (id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed

    {

        return self;

    }

    6.实现<UIViewControllerAnimatedTransitioning>协议方法,下面两个协议方法是必须实现的

    - (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext{

        return 0.3;

    }

    - (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext{

        UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];

            toView.y = -toView.height;

            [UIView animateWithDuration:0.3 animations:^{

                toView.y = 0;

            } completion:^(BOOL finished) {

                [transitionContext completeTransition:YES]; //这个必须写,否则程序 认为动画还在执行中,会导致展示完界面后,无法处理用户的点击事件

            }];

    }

    这样就实现了modal出来的控制器,是从屏幕顶部下来的转场动画

    7. 要实现 控制器消失时的动画,怎么办

    7.1 新增一个类,该类遵守<UIViewControllerAnimatedTransitioning>,新增一个属性,用来区别 显示或消失

    // MYAnimatedTransition.h

    @interface MYAnimatedTransition : NSObject<UIViewControllerAnimatedTransitioning>

    @property (assign,nonatomic) BOOL show;

    @end

    // MYAnimatedTransition.m

    @implementation MYAnimatedTransition

    - (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext

    {

        return 0.3;

    }

    - (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext

    {

        if (self.show == YES) { // 显示  

            UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];

            toView.y = -toView.height;

            [UIView animateWithDuration:0.3 animations:^{

                toView.y = 0;

            } completion:^(BOOL finished) {

                [transitionContext completeTransition:YES];

            }];    

        }else{  // 消失      

            UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];

            [UIView animateWithDuration:0.3 animations:^{

                fromView.y = fromView.height;

            } completion:^(BOOL finished) {

                [transitionContext completeTransition:YES];

            }];

        }

    }

    @end

    7.2 修改自定义转场动画的代理方法,返回MYAnimatedTransition类对象

    #pragma mark - 自定义转场动画的代理方法,两个,分别控制显示和消失

    - (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source

    {

        MYAnimatedTransition *anima = [[MYAnimatedTransition alloc]init];

        anima.show = YES;

        return anima;

    }

    - (id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed

    {

        MYAnimatedTransition *anima = [[MYAnimatedTransition alloc]init];

        anima.show = NO;

        return anima;

    }

    7.3 修改自定义UIPresentationController的.m文件

    - (void)presentationTransitionWillBegin{

        NSLog(@"presentationTransitionWillBegin");

        [self.containerView addSubview:self.presentedView]; // 因为是自定义转场动画,所以添加视图的工作也需要自行实现

    }

    - (void)dismissalTransitionDidEnd:(BOOL)completed

    {

        NSLog(@"dismissalTransitionDidEnd");

        [self.presentedView removeFromSuperview]; // 因为是自定义转场动画,所以移除视图的工作也需要自行实现

    }

    而且下面这个方法作废了,程序是不会执行的,因为你是自定义转场动画,动画前后的Frame都已经在这个方法实现了: - (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext

    - (CGRect)frameOfPresentedViewInContainerView

    {  

      return CGRectMake(100, 100, 150, 300); 

    }

    7.4 要实现更复杂的转场动画,只要改下面这个方法,比如改成3D旋转

    - (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext

    {

            UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];

            // toView.y = -toView.height;

            toView.layer.transform = CATransform3DMakeRotation(M_PI_2, 0, 1, 0);

            [UIView animateWithDuration:0.3 animations:^{

                // toView.y = 0;

                toView.layer.transform = CATransform3DIdentity;

            } completion:^(BOOL finished) {

                [transitionContext completeTransition:YES];

            }];

            

        }else{

            

            UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];

            [UIView animateWithDuration:0.3 animations:^{

                   // fromView.y = fromView.height;

                   fromView.layer.transform = CATransform3DMakeRotation(M_PI_2, 0, 1, 0);

            } completion:^(BOOL finished) {

                [transitionContext completeTransition:YES];

            }];

        }

    }

  • 相关阅读:
    vue富文本编辑器
    vue图片上传组件
    vue全局使用axios插件请求ajax
    vue项目初始化时npm run dev报错webpack-dev-server解决方法
    vue axios使用form-data的形式提交数据
    react-keep-alive
    create-react-app 兼容 ie9
    next-定义路由
    next-支持css样式和按需加载antd
    react-错误边界
  • 原文地址:https://www.cnblogs.com/oumygade/p/4280512.html
Copyright © 2011-2022 走看看