iOS动画实践三(UIView的动画你真的会用吗?)

在这一节中,我们继续讲解UIView中的一些动画的使用,之前已经讲过了基础的用法,和spring动画的用法,在这一节中,我们将要介绍Transitions,也是一个我们经常使用到的动画

首先我们把上次的工程打开,没看上一篇文章的同学,请移步

http://ppsheep.com/2017/01/22/iOS动画实践二-UIView的动画你真的会用吗/

加入、移除、隐藏 view的动画

我们知道Transitions的意思是一个过渡动画、转变动画,但是具体什么效果,我们还是不知道,接下来,我们先来看看这个动画是一个什么要样的效果?

首先我们创建一个animationContainerView,这个就是做动画的view,为什么叫做ContainerView,因为我们还要在这个view中放上其他的一些控件一起来做动画

我们将其他的控件先隐藏掉,加入动画的view看看,是什么效果

1
2
3
animationContainerView = UIView(frame: view.bounds)
animationContainerView?.frame = view.bounds
view.addSubview(animationContainerView!)

然后再viewDidAppear方法中,做一个transition动画

1
2
3
4
5
let newView = UIImageView(image: UIImage(named: "banner"))
newView.center = animationContainerView!.center
UIView.transition(with: animationContainerView!, duration: 0.83, options: [.curveEaseOut,.transitionFlipFromTop], animations: {
self.animationContainerView?.addSubview(newView)
}, completion: nil)

好我们来看看效果

我故意将动画放的很慢,这样效果就能够更明显,这里这个option有很多种效果,我就不全部展示了,这里我提两个比较不一样的

transitionCrossDissolve

这是一个渐渐显示的一个效果

将option参数换掉就行,还是直接看效果

可能模拟器的动画效果不是那么明显,大家可以自己手动实验一下

transitionCurlUp 这个是整个一个view的一个效果

上面我都是使用的addsubview来做动画,要做移除view的动画,或者隐藏的动画,直接变换方法就行,具体的操作,我就不做了

翻转效果

我们新创建一个VC-AnotherViewController

1
2
3
4

UIView.transition(from: view, to: anotherVc.view , duration: 1.0, options: [.curveEaseInOut,.transitionFlipFromLeft]) { (true) in

}

这一行代码就可以实现翻转效果

这种效果也是我们常见的

登录动画

接下来我们在我们之前做的登录页面上,加上一些Transitions的动画

说一下我想要实现的效果,当我们点击登录按钮的时候,有一个动画出现,显示当前的登录进度,就是这么一个简单的实现

一步一步来,首先,在点击按钮的时候,让label出现

1
2
3
4
5
6
//首先将lable加入到view中
//动画的view
let status = UIImageView(image: UIImage(named: "banner"))
let label = UILabel()
let message = ["连接中...","授权中...","发送认证消息...","认证失败..."]
var statusPosition = CGPoint.zero

在页面加载时将status隐藏起来

1
2
3
4
5
6
7
8
9
10
11
12
//首先将label隐藏
status.isHidden = true
status.center = loginBtn.center
view.addSubview(status)

label.frame = CGRect(x: 0, y: 0, width: status.frame.size.width, height: status.frame.size.height)
label.textAlignment = .center
label.font = UIFont(name: "HelveticaNeue", size: 18)
label.textColor = UIColor.blue
status.addSubview(label)

statusPosition = status.center

然后我们在点击的时候,调用方法 showMeesage

1
2
3
4
5
6
7
8
9
func showMessage(index: Int) {
label.text = message[index]
UIView.transition(with: status, duration: 0.5, options: [.curveEaseIn,.transitionFlipFromBottom], animations: {
self.status.isHidden = false
}) { (true) in

}

}

还是看一下效果

加上动效

现在连接的状态是出现了,但是这样它就不动了,我们想要这个状态不断更新,为了实现这样的操作,我们定义一个函数,这个函数是这样的,传入一个重复操作的间隔时间,再传入需要操作的方法,即一个闭包

1
2
3
4
5
6
7
8
// A delay function
func delay(seconds: Double, completion:@escaping ()->()) {
let popTime = DispatchTime.now() + Double(Int64( Double(NSEC_PER_SEC) * seconds )) / Double(NSEC_PER_SEC)

DispatchQueue.main.asyncAfter(deadline: popTime) {
completion()
}
}

上面这个方法的意思是,每几秒钟执行一次completion,因为我们需要更新UI,所以这个completion必须要在主线程中执行

另外我们还需要一个移除状态的方法

1
2
3
4
5
6
7
8
9
10
func removeMessage(index: Int) {
UIView.animate(withDuration: 0.5, delay: 0.0, options: [], animations: {
self.status.center.x += self.view.bounds.size.width
}) { _ in
self.status.isHidden = true
self.status.center = self.statusPosition

self .showMessage(index: index+1)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func showMessage(index: Int) {
label.text = message[index]
UIView.transition(with: status, duration: 0.5, options: [.curveEaseIn,.transitionFlipFromBottom], animations: {
self.status.isHidden = false
}) { _ in

delay(seconds: 2, completion: {
if index < self.message.count-1 {//到了最后一条消息
self.removeMessage(index: index)
}else{

}
})
}
}

看一下效果

好今天就讲到这里,马上要放假咯,收拾收拾,回家过年