前言

前几节中我们学习了改变控件位置/透明度等属性实现的动画,然而如何通过动画的方式添加/移除View呢,这时我们需要用到Transitions动画

transitions示例

添加一个新的view

图片描述

var animationContainerView: UIView?
override func viewDidLoad() {
//set up the animation container animationContainerView = UIView(frame: view.bounds) animationContainerView!.frame = view.bounds view.addSubview(animationContainerView!)
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
//create new view
let newView = UIImageView(image: UIImage(named: "banner")!) newView.center = animationContainerView!.center
//add the new view via transition
UIView.transitionWithView(animationContainerView!, duration: 0.33,
options: [.CurveEaseOut, .TransitionFlipFromBottom], animations: {
self.animationContainerView!.addSubview(newView) }, completion: nil)
}                                  

通过这样一段代码,我们就将一个新的view添加进了self.animationContainerView
我们用到了
transitionWithView(_:duration: options:animations:completion:).
这个方法看起来和标准的UIView动画方法几乎一模一样,它的主要区别在于函数的option参数,比如例子中的.TransitionFlipFromBottom。正是这些参数决定了视图添加进来时的动画
下面是所有预设好的 transition animation options:

  • .TransitionFlipFromLeft

  • .TransitionFlipFromRight

  • .TransitionCurlUp

  • .TransitionCurlDown

  • .TransitionCrossDissolve

  • .TransitionFlipFromTop

  • .TransitionFlipFromBottom

移除一个view

图片描述

//remove the view via transition
UIView.transitionWithView(animationContainerView!, duration: 0.33,
options: [.CurveEaseOut, .TransitionFlipFromBottom], animations: {
self.newView.removeFromSuperview() }, completion: nil)

与前例相似,我们在闭包里调用removeFromSuperview()移除了视图

隐藏/显示view

图片描述

//hide the view via transition
UIView.transitionWithView(self.newView, duration: 0.33, options: [.CurveEaseOut, .TransitionFlipFromBottom], animations: {
self.newView.hidden = true }, completion: nil)

对于hide属性的变化,不需要设置animationContainerView,我们将控件自身作为animationContainerView

以一个view取代其他view

图片描述

//replace via transition
UIView.transitionFromView(self.oldView!, toView: self.newView!, duration: 0.33, options: [.TransitionFlipFromTop],
completion: nil)

我们使用transitionFromView方法,用newView替代了oldView

DEMO

我们继续上次做的登录界面
图片描述
我们这次希望添加上如图的登录状态指示,并修改其内容,动画改变登录状态
首先我们在viewDidLoad方法中隐藏status,并将登录信息存储在一个Array中
随后我们写一个showMessage方法来展示状态

    /**
    展示登录状态
    
    - parameter index: Message数组的索引
    */
func showMessage(index index: Int) { label.text = messages[index]
UIView.transitionWithView(status, duration: 0.33, options: [.CurveEaseOut, .TransitionCurlDown], animations: {
self.status.hidden = false }, completion: {_ in
//transition completion
}) }

这个函数中我们通过transitionWithView(_:duration:options:animations: completion:) 方法,将状态添加进了视图中,我们使用的是TransitionCurlDown样式,效果如图
图片描述
随后找到我们上次为LoginButton写的方法

animations: { self.loginButton.bounds.size.width += 80.0
}, completion: nil)

我们中completion闭包中调用我们的showMassage方法

completion: {_ in self.showMessage(index: 0)
}

Note:

如果觉得动画的速度点速度太快以至于没有看清楚,我们可以在模拟器中打开
Debug/Toggle Slow Animations in Frontmost App功能来减慢动画的执行速度,这样我们就可以方便的去调整我们的动画了

下一个动画中我们需要先去记录banner的位置,这样才能把下一个视图加入到合适的位置,添加一个变量statusPosition记录位置
var statusPosition = CGPoint.zero
viewDidLoad的末尾添加statusPosition = status.center记录位置
接下来我们来实现消息的移除

    /**
    移除登录状态
    
    - parameter index: Message数组的索引
    */
func removeMessage(index index: Int) {
UIView.animateWithDuration(0.33, delay: 0.0, options: [], animations:
{
self.status.center.x += self.view.frame.size.width
}, completion: {_ in
//动画结束后移回原位并隐藏
self.status.hidden = true self.status.center = self.statusPosition
self.showMessage(index: index+1) })
}

这样我们很容易的结合了标准UIView动画与transitions动画,我们仅仅通过这些API和UIKit,在后台调用了响应的Core Animation元素
现在我们来完成showMessage和removeMessage的链条
找到showMessage方法中的注释//transition,替换为如下代码

delay(seconds: 2.0) {
if index < self.messages.count-1 {
self.removeMessage(index: index) } else {
//reset form
} }

*delay函数为休眠当前线程2s,模拟网络连接延迟
这样我们已经实现了动画改变登录状态
图片描述

总结

transition动画是UIView动画重要的一部分,也是在UIKit中唯一能实现3D效果动画的方法


Hydrogen
2.5k 声望73 粉丝

Write code for fun.