前言

iOS 7以后提供了自定义转场动画的功能,我们可以通过遵守协议完成自定义转场动画。本篇文章讲解如何实现自定义presentdismiss自定义动画。

效果图

本篇文章实现的动画切换效果图如下:

视图切换种类

如下效果图,这是有两大类视图切换动画的,一种是交互式的,另一种就是自定义的。

本篇只讲其中的UIViewControllerAnimatedTransitioning协议,来实现presentdismiss动画效果。另外的几个,后面会继续学习总结!!!

协议

我们要实现presentdismiss自定义转场效果,我们必须要有一个遵守了UIViewControllerAnimatedTransitioning协议且实现其必须实现的代理方法的类。

我们先来学习UIViewControllerAnimatedTransitioning协议:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 
@protocol UIViewControllerAnimatedTransitioning <NSObject>
 
// This is used for percent driven interactive transitions, as well as for container
// controllers that have companion animations that might need to
// synchronize with the main animation.
//
// 指定转场动画时长,必须实现,否则会Crash。
// 这个方法是为百分比驱动的交互转场和有对比动画效果的容器类控制器而定制的。
- (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext;
 
// This method can only  be a nop if the transition is interactive
// and not a percentDriven interactive transition.
// 若非百分比驱动的交互过渡效果,这个方法只能为空
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext;
 
 
@optional
 
// This is a convenience and if implemented will be invoked by the system
// when the transition context's completeTransition: method is invoked.
- (void)animationEnded:(BOOL) transitionCompleted;
 
@end
 

我们要实现目标效果,就需要一个定义一个类遵守UIViewControllerAnimatedTransitioning协议并实现相应的代理方法。

遵守UIViewControllerAnimatedTransitioning协议

下面,我们来定义一个转场类,这个类必须要遵守UIViewControllerAnimatedTransitioning协议,如下:

头文件

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 
//
//  HYBModalTransition.h
//  PresentDismissTransitionDemo
//
//  Created by huangyibiao on 15/12/21.
//  Copyright © 2015年 huangyibiao. All rights reserved.
//
 
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
 
typedef NS_ENUM(NSUInteger, HYBModalTransitionType) {
  kHYBModalTransitionPresent = 1 << 1,
  kHYBModalTransitionDismiss = 1 << 2
};
 
@interface HYBModalTransition : NSObject <UIViewControllerAnimatedTransitioning>
 
/*!
*  @author 黄仪标, 15-12-21 11:12:44
*
*  指定动画类型
*
*  @param type          动画类型
*  @param duration      动画时长
*  @param presentHeight 弹出呈现的高度
*  @param scale         fromVC的绽放系数
*
*  @return
*/
+ (HYBModalTransition *)transitionWithType:(HYBModalTransitionType)type
                                  duration:(NSTimeInterval)duration
                             presentHeight:(CGFloat)presentHeight
                                     scale:(CGPoint)scale;
 
@end
 

我们只公开了一个方法来创建,指定动画类型,动画时长,呈现的高度,缩放系数。

实现文件

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
 
//
//  HYBModalTransition.m
//  PresentDismissTransitionDemo
//
//  Created by huangyibiao on 15/12/21.
//  Copyright © 2015年 huangyibiao. All rights reserved.
//
 
#import "HYBModalTransition.h"
 
@interface HYBModalTransition ()
 
@property (nonatomic, assign) HYBModalTransitionType type;
@property (nonatomic, assign) CGFloat presentHeight;
@property (nonatomic, assign) CGPoint scale;
@property (nonatomic, assign) NSTimeInterval duration;
 
@end
 
@implementation HYBModalTransition
 
+ (HYBModalTransition *)transitionWithType:(HYBModalTransitionType)type
                                  duration:(NSTimeInterval)duration
                             presentHeight:(CGFloat)presentHeight
                                     scale:(CGPoint)scale {
  HYBModalTransition *transition = [[HYBModalTransition alloc] init];
  
  transition.type = type;
  transition.presentHeight = presentHeight;
  transition.scale = scale;
  transition.duration = duration;
  
  return transition;
}
 
#pragma mark - UIViewControllerAnimatedTransitioning
- (void)animationEnded:(BOOL)transitionCompleted {
  NSLog(@"%s", __FUNCTION__);
}
 
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext {
  return self.duration;
}
 
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
  switch (self.type) {
    case kHYBModalTransitionPresent: {
      [self present:transitionContext];
      break;
    }
    case kHYBModalTransitionDismiss: {
      [self dismiss:transitionContext];
      break;
    }
    default: {
      break;
    }
  }
}
 
#pragma mark - Private
- (void)present:(id<UIViewControllerContextTransitioning>)transitonContext {
  UIViewController *fromVC = [transitonContext viewControllerForKey:UITransitionContextFromViewControllerKey];
  UIViewController *toVC = [transitonContext viewControllerForKey:UITransitionContextToViewControllerKey];
  UIView *containerView = [transitonContext containerView];
  
  // 对fromVC.view的截图添加动画效果
  UIView *tempView = [fromVC.view snapshotViewAfterScreenUpdates:NO];
  tempView.frame = fromVC.view.frame;
  
  // 对截图添加动画,则fromVC可以隐藏
  fromVC.view.hidden = YES;
  
  // 要实现转场,必须加入到containerView中
  [containerView addSubview:tempView];
  [containerView addSubview:toVC.view];
  
  // 我们要设置外部所传参数
  // 设置呈现的高度
  toVC.view.frame = CGRectMake(0,
                               containerView.frame.size.height,
                               containerView.frame.size.width,
                               self.presentHeight);
  
  // 开始动画
  __weak __typeof(self) weakSelf = self;
  [UIView animateWithDuration:self.duration delay:0.0 usingSpringWithDamping:0.5 initialSpringVelocity:1.0 / 0.5 options:0 animations:^{
    // 在Y方向移动指定的高度
    toVC.view.transform = CGAffineTransformMakeTranslation(0, -weakSelf.presentHeight);
    
    // 让截图缩放
    tempView.transform = CGAffineTransformMakeScale(weakSelf.scale.x, weakSelf.scale.y);
  } completion:^(BOOL finished) {
    if (finished) {
      [transitonContext completeTransition:YES];
    }
  }];
}
 
- (void)dismiss:(id<UIViewControllerContextTransitioning>)transitonContext {
  UIViewController *fromVC = [transitonContext viewControllerForKey:UITransitionContextFromViewControllerKey];
  UIViewController *toVC = [transitonContext viewControllerForKey:UITransitionContextToViewControllerKey];
  UIView *containerView = [transitonContext containerView];
  
  // 取出present时的截图用于动画
  UIView *tempView = containerView.subviews.lastObject;
  
  // 开始动画
  [UIView animateWithDuration:self.duration animations:^{
    toVC.view.transform = CGAffineTransformIdentity;
    fromVC.view.transform = CGAffineTransformIdentity;
 
  } completion:^(BOOL finished) {
    if (finished) {
      [transitonContext completeTransition:YES];
      toVC.view.hidden = NO;
      
      // 将截图去掉
      [tempView removeFromSuperview];
    }
  }];
}
 
@end
 

我们这里就不细讲了,因为在iOS 7 push/pop转场动画中已经讲过了。大家若未看过,可以先阅读。

测试效果

我们要设置一下被present的控制器的代理,在-viewDidLoad:时添加如下代码:

 
1
2
3
4
5
 
// 配置一下代理防呈现样式为自定义
self.transitioningDelegate = self;
self.modalPresentationStyle =  UIModalPresentationCustom;
 

同时,还需要遵守协议并实现协议UIViewControllerTransitioningDelegate,这个是控制器转场动画实现的代理:

 
1
2
3
4
5
6
7
8
9
10
 
#pragma mark - UIViewControllerTransitioningDelegate
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {
   return [HYBModalTransition transitionWithType:kHYBModalTransitionPresent duration:0.5 presentHeight:350 scale:CGPointMake(0.9, 0.9)];
}
 
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {
  return [HYBModalTransition transitionWithType:kHYBModalTransitionDismiss duration:0.25 presentHeight:350 scale:CGPointMake(0.9, 0.9)];
}
 

我们设置presentdismiss自定义对象,就可以实现我们的动画了。

想要实现什么样的动画,都可以在HYBModalTransition类里面实现,没有实现不了,只有想不到!!!

iOS 7 present/dismiss转场动画的更多相关文章

  1. 自定义Push/Pop和Present/Dismiss转场

    项目概述 iOS中最常见的动画无疑是Push和Pop的转场动画了,其次是Present和Dismiss的转场动画. 如果我们想自定义这些转场动画,苹果其实提供了相关的API,在自定义转场之前,我们需要 ...

  2. 【Swift】IOS开发中自定义转场动画

    在IOS开发中,我们model另外一个控制器的时候,一般都使用默认的转场动画. 其实我们可以自定义一些转场动画.达到不同的转场效果. 步骤如下:(photoBrowser是目标控制器) 1.在源控制器 ...

  3. iOS 页面之间的转场动画控制器间的转换

    CATransition类实现层的转场动画.你可以从一组预定义的转换或者通过提供定制的CIFilter实例来指定转场效果. 例如:控制器之间的跳转 LoginViewController *myVC ...

  4. iOS-自定义Model转场动画-仿酷我音乐播放器效果

    周末,闲来无事,仿写了酷我音乐播放器效果: 效果图如下: 实现思路: 1.实现手势处理视图旋转 2.自定义Model动画: 1.手势是利用了一个UIPanGestureRecognizer手势: 注意 ...

  5. iOS 自定义转场动画浅谈

    代码地址如下:http://www.demodashi.com/demo/11612.html 路漫漫其修远兮,吾将上下而求索 前记 想研究自定义转场动画很久了,时间就像海绵,挤一挤还是有的,花了差不 ...

  6. iOS:探究视图控制器的转场动画

    一.介绍 在iOS开发中,转场动画的使用无处不见,不只是我们自己更多的使用UIViewblock动画实现一个转场动画,其实,在我们实现VC控制器跳转的时候都是转场动画的实现,例如标签栏控制器的切换.模 ...

  7. iOS 动画学习之视图控制器转场动画

    一.概述 1.系统会创建一个转场相关的上下文对象,传递到动画执行器的animateTransition:和transitionDuration:方法,同样,也会传递到交互Controller的star ...

  8. iOS 转场动画探究(一)

    什么是转场动画: 转场动画说的直接点就是你常见的界面跳转的时候看到的动画效果,我们比较常见的就是控制器之间的Push和Pop,还有Present和Dismiss的时候设置一下系统给我们的modalTr ...

  9. iOS 转场动画探究(二)

    这篇文章是接着第一篇写的,要是有同行刚看到的话建议从前面第一篇看,这是第一篇的地址:iOS 转场动画探究(一) 接着上一篇写的内容: 上一篇iOS 转场动画探究(一)我们说到了转场要素的第四点,把那个 ...

随机推荐

  1. left join 与left outer join的区别

    joinn 语句有三种:inner join, left outer join 和 right outer join都可以简写,分别为join,left join,right join.

  2. bzoj1709 [Usaco2007 Oct]Super Paintball超级弹珠 暴力

    [Usaco2007 Oct]Super Paintball超级弹珠 Description 奶牛们最近从著名的奶牛玩具制造商Tycow那里,买了一套仿真版彩弹游戏设备(类乎于真人版CS). Bess ...

  3. 线段上的格点 辗转相除法(GCD)

    /*问题描述:线段上的格点给定平面上的两个格点 P1 = (x1, y1) ; P2 = (x2, y2) 线段P1 P2上,除P1 和 P2以外一共有几个格点*//*分析过程在格点上画P1(0,5) ...

  4. [NOIP2002] 提高组 洛谷P1031 均分纸牌

    题目描述 有 N 堆纸牌,编号分别为 1,2,…, N.每堆上有若干张,但纸牌总数必为 N 的倍数.可以在任一堆上取若于张纸牌,然后移动. 移牌规则为:在编号为 1 堆上取的纸牌,只能移到编号为 2 ...

  5. 库操作&表操作

    系统数据库 ps:系统数据库: mysql 授权库,主要存储系统用户的 权限信息 test MySQL数据库系统自动创建的 测试数据库 ination_schema 虚拟库,不占用磁盘空间,存储的是数 ...

  6. Python()-类命名空间和对象/实例命名空间

    类命名空间和对象/实例命名空间: 创建类, 就会创建一个类的名称空间, 空间:存储类的属性 属性: 静态属性:直接定义在类下面 & 和类名关联 的变量 对象属性:在类内和self关联 & ...

  7. HUNAN 11567 Escaping (最大流)

    http://acm.hunnu.edu.cn/online/?action=problem&type=list&courseid=0&querytext=&pagen ...

  8. Windows如何在cmd命令行中查看、修改、删除与添加、设置环境变量

    首先明确一点: 所有的在cmd命令行下对环境变量的修改只对当前窗口有效,不是永久性的修改.也就是说当关闭此cmd命令行窗口后,将不再起作用.永久性修改环境变量的方法有两种:一种是直接修改注册表(此种方 ...

  9. Eclipse的JQuery提示插件-Spket(别试了,没什么效果,且安装设置麻烦)

    参考: http://www.cnblogs.com/shulin/archive/2010/08/09/1796146.html 我测试了,但是没用起来,原因有如下几点: 1.配置复杂,且提示效果不 ...

  10. Visual Studio VS2010 如何修改默认的编辑语言

    1 比如我要把默认是C++的配置改成C#,在工具-导入和导出设置中,重置所有设置 2 这里改成新的语言 3 重置完成