iOS ViewContrller转场动画学习笔记

iOS ViewContrller转场动画学习笔记

本文只用来记录学习的modal方式的转场,一般需要实现的动画包括:presentation,dismissal两种可能实现的动画.

FromView 和 ToView

在代码中,经常使用FromViewToView.FromView表示当前的视图view,ToView表示要跳转的视图View.例如,presentation中,Avc present 出 Bvc,则A的view视图就是FromView,而B的view就是ToView.相反,dismissal中,从Bvc dismiss 到Avc,此时Bvc的视图view就是FromView,A的视图view就是ToView.

Presenting和presented

这组概念也很重要,容易和上面的FromView,ToView混淆.如果是Avc present Bvc,那么A就是Presenting,B就是presented.不论当时的动作是Presentation还是Dismissal.UIKit中讲A称为presentingViewController,B称为presentedViewController.通过主动或者被动很容易区分出来.

modalPrentationStyle

viewController中关于modal相关的属性: FullScreenCustom两种.区别在与FullScreen时候在containerView中会主动移除fromView,而Custom模式中,containerView不会主动移除fromView.

这个属性的特点非常重要.如果需要present方式时候想看到presentingViewController的view,那么这里一定要设置成Custom.

自定义转场动画

最简单的转场动画需要如下步骤:

  • 创建一个遵守UIViewControllerAnimatedTransitioning协议的对象
  • 实现该协议的两个重要的方法
//指定转场动画持续的时长
func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval      
//转场动画的具体内容       
func animateTransition(transitionContext: UIViewControllerContextTransitioning)
  • 使得presentingViewController或者创建一个类遵守UIViewControllerTransitioningDelegate协议,并且实现如下两个方法,返回一个前面创建的满足Animation协议的对象
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning?
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning?
  • 设置presentedViewController的transitioningDelegate属性

上面步骤中,所有的动画都在func animateTransition(transitionContext:)中完成,这里需要发挥你的想象力.具体的FromViewToView的动画如何展现.

特殊的Modal转场

这里直接引用的参考文章中的内容 -- 非常重要

Modal 转场中需要做的事情和两种容器 VC 的转场一样,但在细节上有些差异。UINavigationController 和 UITabBarController 这两个容器 VC 的根视图在屏幕上是不可见的(或者说是透明的),可见的只是内嵌在这两者中的子 VC 中的视图,转场是从子 VC 的视图转换到另外一个子 VC 的视图,其根视图并未参与转场;而 Modal 转场,以 presentation 为例,是从 presentingView 转换到 presentedView,根视图 presentingView 也就是 fromView 参与了转场。而且 NavigationController 和 TabBarController 转场中的 containerView 也并非这两者的根视图。

Modal 转场与两种容器 VC 的转场的另外一个不同是:Modal 转场结束后 presentingView 可能依然可见,UIModalPresentationPageSheet 模式就是这样。这种不同导致了 Modal 转场和容器 VC 的转场对 fromView 的处理差异:容器 VC 的转场结束后 fromView 会被主动移出视图结构,这是可预见的结果,我们也可以在转场结束前手动移除;而 Modal 转场中,presentation 结束后 presentingView(fromView) 并未主动被从视图结构中移除。准确来说,是 UIModalPresentationCustom 这种模式下的 Modal 转场结束时 fromView 并未从视图结构中移除;UIModalPresentationFullScreen 模式的 Modal 转场结束后 fromView 依然主动被从视图结构中移除了。这种差异导致在处理 dismissal 转场的时候很容易出现问题,没有意识到这个不同点的话出错时就会毫无头绪。下面来看看 dismissal 转场时的场景。

ContainerView 在转场期间作为 fromView 和 toView 的父视图。三种转场过程中的 containerView 是 UIView 的私有子类,不过我们并不需要关心 containerView 具体是什么。在 dismissal 转场中:

  • UIModalPresentationFullScreen 模式:presentation 后,presentingView 被主动移出视图结构,在 dismissal 中 presentingView 是 toView 的角色,其将会重新加入 containerView 中,实际上,我们不主动将其加入,UIKit 也会这么做,前面的两种容器控制器的转场里不是这样处理的,不过这个差异基本没什么影响。
  • UIModalPresentationCustom 模式:转场时 containerView 并不担任 presentingView 的父视图,后者由 UIKit 另行管理。在 presentation 后,fromView(presentingView) 未被移出视图结构,在 dismissal 中,注意不要像其他转场中那样将 toView(presentingView) 加入 containerView 中,否则本来可见的 presentingView 将会被移除出自身所处的视图结构消失不见。如果你在使用 Custom 模式时没有注意到这点,就很容易掉进这个陷阱而很难察觉问题所在,这个问题曾困扰了我一天。

小结:建议是,不要干涉官方对 Modal 转场的处理,我们去适应它。在 Custom 模式下,由于 presentingView 不受 containerView 管理,在 dismissal 转场中不要像其他的转场那样将 toView(presentingView) 加入 containerView,否则 presentingView 将消失不见,而应用则也很可能假死;在 presentation 转场中,切记不要手动将 fromView(presentingView) 移出其父视图。

iOS 8 为协议添加了viewForKey:方法以方便获取 fromView 和 toView,但是在 Modal 转场里要注意,从上面可以知道,Custom 模式下,presentingView 并不受 containerView 管理,这时通过viewForKey:方法来获取 presentingView 得到的是 nil,必须通过viewControllerForKey:得到 presentingVC 后来获取。因此在 Modal 转场中,较稳妥的方法是从 fromVC 和 toVC 中获取 fromView 和 toView。

总结要点

  • 一般来说,Modal 转场的delegate由 presentedVC 提供
  • 在presentation/push时候,要调用containerView.addSubView(toView),toView加入到containerView是每个转场必须完成的一步.modal中的Custom模式下的Dismiss 里不要将 toView添加到containerView,因为在present的时候,系统就没有将它从containerView中删除.
  • 在UIView.animation的completion中要调用如下代码:
//2
let isCancelled = transitionContext.transitionWasCancelled()
transitionContext.completeTransition(!isCancelled)
  • Modal 转场一般需要 presentedVC 来提供转场UIViewControllerTransitioningDelegate的代理. modal方式中自定义转场时,决定转场动画效果的modalTransitionStyle属性将被忽略.具体动画由代理中返回的animationController决定

参考文献

https://github.com/wazrx/XWTrasitionPractice

http://www.jianshu.com/p/45434f73019e

http://www.cocoachina.com/ios/20160309/15605.html

偶然遇到的crash:

1 怎么连续dismiss两个viewController?
直接[self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];就可以了,控制器堆栈是dismiss掉下面的,上面的自动就dismiss了.或者直接将动画设置成No

2 连续push或者present会crash - 因为动画的问题.如果有此类需求.直接关闭动画

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

推荐阅读更多精彩内容