iOS-总结Demo--Push、Pop 、Present、Dissmiss动画

梧桐更兼细雨,到黄昏、点点滴滴。这次第,怎一个、愁字了得!<爱心鱼>

小结一下跳转页面的动画效果实现思路!
代码移步GitHub

总结的转场动画是下面几个情况:

  • 导航控制器的 Push 动画和 Pop 动画
  • 普通控制器的 Present 动画和 Dismiss动画,

思路简析:

  • 跳转的控制器遵守 UINavigationControllerDelegate 协议,从而实现 Pop 和 Push 的跳转动画。

通过 operation == UINavigationControllerOperationPush 或者 UINavigationControllerOperationPop 区分是 Push 还是 Pop

  • (nullable id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
    animationControllerForOperation:(UINavigationControllerOperation)operation
    fromViewController:(UIViewController *)fromVC
    toViewController:(UIViewController *)toVC```
  • 跳转的控制器遵守UIViewControllerTransitioningDelegate协议, 从而实现 Present 和 Dissmiss跳转动画

Present:

  • (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source;

Dissmiss:

  • (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed;```
  • <big><u><b>上述的几个方法都是 返回一个遵守UIViewControllerAnimatedTransitioning协议的对象,而主要的动画实现就是写在这个对象当中!我们只要封装好这个类型的对象,在上述方法中返回对应实例对象就能实现动画效果!</big></u></b>

UIViewControllerAnimatedTransitioning协议 主要实现两个方法

-(NSTimeInterval)transitionDuration: transitionContext: 跳转的时间
-(void)animateTransition: transitionContext 所要执行的动画在这里实现 ```

其中第二个方法传入的参数是泛型的UIViewControllerContextTransitioning对象
可以通过下面它的的实例方法获取我们需要展示动画的相关属性

#  这个方法获得的是 控制整个跳转的页面 (API 描述:这个视图是动画发生的地方(画布))(将要跳转到的控制器的view添加到画布上执行动画)
- (nullable UIView *)containerView
#  Key 取值 UITransitionContextFromViewControllerKey  (源控制器)UITransitionContextToViewControllerKey(目标控制器)
- (nullable __kindof UIViewController *)viewControllerForKey:(NSString *)key
#  Key 取值  UITransitionContextFromViewKey(源视图)  UITransitionContextToViewKey(目标视图)
- (nullable __kindof UIView *)viewForKey:(NSString *)key

简单效果展示:

演示——跳转.gif

上代码:

第一步: 是封装一个实现动画的类(PP_Transition),遵循UIViewControllerAnimatedTransitioning协议

PP_Transition.h中

  • 导入 UIKit 框架

import <UIKit/UIKit.h> ```

  • 定义一个枚举类型,方便我们区分场景

枚举判断使用场景

typedef NS_OPTIONS(NSUInteger, AnimatedScene)
{
AnimatedScenePush = 0, // 值为 0
AnimatedScenePop = 1 << 0, // 值为 2 的 0次
AnimatedScenePresent = 1 << 1, // 值为 2 的 1次
AnimatedSceneDissmiss = 1 << 2 // 值为 2 的 2次
};

- 声明一个自定义初始化方法

>```code
- (instancetype)initWithStytle:(AnimatedScene)scene;```

-------
####PP_Transition.m中
>- 延展一个属性 用来记录初始化的类型

>```code
{
    AnimatedScene _scenceStyle;
}```
- 实现自定义初始化方法

>```code
- (instancetype)initWithStytle:(AnimatedScene)scene
{
    if (self = [super init])
    {
        _scenceStyle = scene;
    }
    return self;
}
  • 实现协议方法1: 转场动画持续时间
  • (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext{
    return 1.0;
    }```
  • 实现协议方法2: 具体去实现转场的动画 (这里我就是简单的实现几个动画, 我们可以根据具体的情况加以实现)
  • 如果我们想加一些更好的效果,可以尝试在画布(containerView) View 上加上一些自定义的View 用来遮挡或者当做背景(比如 Pop回来时候目标View变大时候加一个背景),记住最后移除掉就行!这是一种思路!
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
   // 获取到 containerView视图 (我们动画发生的载体)
   UIView *containerView = [transitionContext containerView];
   // 我们要去的 View
   UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
   // 从哪个 View 去的
   UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
    switch (_scenceStyle)
   {
       case AnimatedScenePush:
       {// Push 动画 这里只是举个例子  动画效果可以自己去使用
           // 注意点: 一定要把目的视图(要去的 View) 添加到容器(containerView)上.
           [UIView animateWithDuration:1.0 animations:^{
               fromView.transform = CGAffineTransformMakeScale(0.5, 0.5);
           } completion:^(BOOL finished) {
               [containerView addSubview:toView];
               // 这个方法大概就是完成过渡动画,更新内部视图,控制器状态的转变!
               [transitionContext completeTransition:YES];
           }];
           
           NSLog(@"Push 动画效果");
       }
          break;
       case AnimatedScenePop:
       {
           // Pop 动画
           [UIView animateWithDuration:1.0 animations:^{
               // 让当前的二级页面  从下方消失
               fromView.frame = CGRectMake(0, kScreenH, kScreenW, kScreenH);
               
           } completion:^(BOOL finished) {
               
               [containerView addSubview:toView];
               
               [UIView animateWithDuration:1.0 animations:^{
                   // 让首级页面  由小变大
                   toView.transform = CGAffineTransformMakeScale(1, 1);
                   
               } completion:^(BOOL finished) {
                   
                   // 完成过度动画
                   [transitionContext completeTransition:YES];
               }];
           }];
           NSLog(@"Pop 动画效果");

       }
           
           break;
       case AnimatedScenePresent:
       {
           
           toView.frame = CGRectMake(kScreenW / 2.0 , kScreenH / 2.0, 0, 0);
           
           [containerView addSubview:toView];
           
           [UIView animateWithDuration:1.0 animations:^{
             
              toView.frame = CGRectMake(0 , 0, kScreenW, kScreenH);
           
           } completion:^(BOOL finished) {
               
               [transitionContext completeTransition:YES];
           }];
           
           NSLog(@"Present 动画效果");
           

       }
           break;
       case AnimatedSceneDissmiss:
       {
         
           [UIView animateWithDuration:1.0 animations:^{
           // 让当前的二级页面  从上方消失
               fromView.frame = CGRectMake(0, -kScreenH, kScreenW, kScreenH);
               
           } completion:^(BOOL finished) {
               
               [containerView addSubview:toView];
           // 完成过度动画
               [transitionContext completeTransition:YES];
            
           }];
           NSLog(@"Dissmiss 动画效果");

       }
           break;
           
       default:
           break;
   }

}

在跳转的控制器中:

  • 首先遵守<UIViewControllerTransitioningDelegate, UINavigationControllerDelegate>代理
  • 设置代理
     // 设置 导航控制器代理完成 push 和 pop
    self.navigationController.delegate = self;
     // 设置 模态转场过渡代理
    目的控制器Vc.transitioningDelegate = self;
    目的控制器Vc.modalPresentationStyle = UIModalPresentationCustom;```

>- 代理方法实现

```code
// 导航控制器的跳转动画代理方法  在这里完成 Push 和 Pop 动画
- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC
{
    return operation == UINavigationControllerOperationPush ? [[PP_Transition alloc] initWithStytle:(AnimatedScenePush)] : [[PP_Transition alloc] initWithStytle:(AnimatedScenePop)];
}

// 完成转场 Present 动画代理
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{
    NSLog(@"----------->Present 一级视图控制器中");
    return [[PP_Transition alloc] initWithStytle:(AnimatedScenePresent)];
}
// 转场 Dissmiss 动画 代理
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
    NSLog(@"----------->Dissmiss 一级视图控制器中");
    return [[PP_Transition alloc] initWithStytle:(AnimatedSceneDissmiss)];
}

最后说一句:

我开始写的类名不太好, 弄了一半想改的话可以这样!

.h选中要改的类名 ---> 菜单栏选中 Edit ---> Refactor ---> Rename

<b><big>改过之后,之前用到这个类名的地方全部都换过来了</big><b>.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容