iOS控制器转场动画

iOS ViewContrller转场动画学习笔记

2017-01-23  本文已影响264人  brownfeng

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.

自定义转场动画

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

//指定转场动画持续的时长
func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval      
//转场动画的具体内容       
func animateTransition(transitionContext: UIViewControllerContextTransitioning)
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning?
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning?

上面步骤中,所有的动画都在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 转场中:

小结:建议是,不要干涉官方对 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。

总结要点

//2
let isCancelled = transitionContext.transitionWasCancelled()
transitionContext.completeTransition(!isCancelled)

参考文献

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 - 因为动画的问题.如果有此类需求.直接关闭动画

上一篇 下一篇

猜你喜欢

热点阅读