自定义Modal Transition
序
iOS 7提供了一套新的自定义转场动画的API,这套API可以大大降低了我们自定过渡动画的难度。下面用Ray Wenderlich的一张流程图说明API各个部分的作用。
可以看到一个ViewController被呈现或者消除的时候,UIKit会想Transition Delegate请求一个Animator,Animator负责转场动画的实现。可见我们需要自定义个Animator。
一个Animator应该遵循UIViewControllerAnimatedTransitioning
协议,这个包含三个方法:
1 | func transitionDuration(_ transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval |
这里出现了一个UIViewControllerContextTransitioning,它是转场动画的上下文对象,通过它可以获得将要被显示的view、将要被消除的view、将要显示的viewController等等相关对象。需要注意一定是,可能你自己持有了destinationController,但是,但是,但是,一定要通过transitionContext对象来获得desctinationController,以避免出现一些棘手的错误。
开始
下面我们就来着手写一个Modal Transition。这个转场动画参考了Bubble Transition
先看一下效果:
首先创建一个BubbleTransition类。
1 | class BubbleTransition: NSObject { |
BubbleTransition现在只是定义了一个变量,其中最主要的是BubbleTransitionType,present
表示显示viewController,dismiss
表示消除viewController。startPoint
是将要呈现的viewController.view的起始位置,后面我们将看到它的作用。
现在我们利用扩展来BubbleTransition实现UIViewControllerAnimatedTransitioning协议。
1 | extension BubbleTransition: UIViewControllerAnimatedTransitioning { |
先解释一下整体的思路:
小圆圈表示button的位置,点击button会呈现我们要显示的view,就称它是modalView吧。在动画发生之前,我们在containerView中加入一个bubbleView,然后加入modalView(顺序很重要),bubbleView就作为modalView的背景,它们一起从0.001的比例缩放到1比例,这样看起来就像是一个气泡的效果。因为气泡要充满整个屏幕,所以我们就要像上述图示所示的那样得到最大的半径,然后将bubbleView的长宽设置为半径的两倍。
对应标签位置的解释:
- 转场动画的时间长度
- 得到bubbl视图的frame,将它的缩放比列设为0.001,然后添加到containerView中
- 添加将要呈现的视图,将它的比例也设置为0.001,以便和bubble视图一起放到
- 在动画结束之后一定要调用transitionContext.completeTransition(true)以表示这次转场动画结束。
- dismiss基本上是present的逆过程,需要注意的是在动画完成后要把bubble视图和modalView从containerView中移除。
- 计算最大半径,并返回bubbleView的Frame。
最后,为了让我们的BubbleTransition成为转场动画的Animator,我们要在prepareForSegue中设置destinationController的transitioningDelegate,并实现协议对应的方法。
1 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { |