前段时间看了些,动画方面的文章,有一个很不错的教程:iOS-Core-Animation-Advanced-Techniques,看会这个动画方面基本上差不多了,剩下的就是举一反三了。

疏于原先没有太过关注 Facebook 的 POP 动画引擎 ,做的效果这么好,于是就研究了下,找到了些几篇很好的文章:

POP 使用指南:

http://geeklu.com/2014/05/facebook-pop-usage/

很好的 POP 示例教程:

https://github.com/schneiderandre/popping
https://github.com/kejinlu/facebook-pop-sample

上面都是 Objective-C 写的,况且 Swift 出来已经一年了,由于公司项目一直使用 Objective-C,Swift 也得加强学习,故以后做 Demo 就用 Swift 了。

OK,那就仿 Popping ,用 Swift 写一个 POP 动画:SwiftPopping 。效果如下:

POP

桥接

POP 动画引擎是用 Objective-C 写的,想要用在 Swift 项目中,需要用到桥接。

开始桥接项目:前提是创建了 SwiftPopping 项目并且添加了 POP。

第一步:创建桥接文件:SwiftPopping-Bridging-Header.h
第二步:在 SwiftPopping-Bridging-Header.h 文件中写入:#import <pop/POP.h>
第三步:详见下图:

POP

需要注意的地方就是 1 中 SwiftPopping-Bridging-Header.h 所在项目的位置。

OK ,编译运行,成功!

如果想在 Objective-C 项目中调用 Swift 代码,可以参考下面的文章:

http://www.shimingwei.com/iOS/OC_Use_Swift.html

创建按钮 FlatButton

由于我们需要自定义 UIButton 的一些效果(点进去缩放、出来还原效果),故创建一个 FlatButton ,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import UIKit
class FlatButton: UIButton {
//标题居上下左右间距
override var titleEdgeInsets: UIEdgeInsets {
get{
return UIEdgeInsetsMake(4.0,28.0,4.0,28.0)
}
set{
self.titleEdgeInsets = newValue
}
}
class func button() -> FlatButton {
var button = buttonWithType(UIButtonType.Custom) as! FlatButton
return button
}
override init(frame: CGRect) {
super.init(frame: frame)
setup()//设置按钮
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
//内容大小
override func intrinsicContentSize() -> CGSize {
var size = super.intrinsicContentSize()
return CGSizeMake(size.width + self.titleEdgeInsets.left + self.titleEdgeInsets.right,
size.height + self.titleEdgeInsets.top + self.titleEdgeInsets.bottom)
}
/**
设置按钮
*/
func setup() {
self.backgroundColor = self.tintColor;
self.layer.cornerRadius = 4.0
self.setTitleColor(UIColor.whiteColor(), forState: UIControlState.Normal)
self.titleLabel?.font = UIFont(name: "Avenir-Medium", size: 22)
//添加事件
self.addTarget(self, action: "scaleToSmall", forControlEvents: UIControlEvents.TouchDown | UIControlEvents.TouchDragEnter)
self.addTarget(self, action: "scaleAnimation", forControlEvents: UIControlEvents.TouchUpInside)
self.addTarget(self, action: "scaleToDefault", forControlEvents: UIControlEvents.TouchDragExit)
}
//缩小
func scaleToSmall() {
var scaleAnimation = POPBasicAnimation(propertyNamed: kPOPLayerScaleXY)
scaleAnimation.toValue = NSValue(CGPoint:CGPointMake(0.95, 0.95))
self.layer.pop_addAnimation(scaleAnimation, forKey: "scaleToSmallAnimation")
}
//还原
func scaleToDefault() {
var scaleAnimation = POPBasicAnimation(propertyNamed: kPOPLayerScaleXY)
scaleAnimation.toValue = NSValue(CGPoint:CGPointMake(1, 1))
self.layer.pop_addAnimation(scaleAnimation, forKey: "scaleToDefaultAnimation")
}
//动画
func scaleAnimation() {
var scaleAnimation = POPSpringAnimation(propertyNamed: kPOPLayerScaleXY)
scaleAnimation.toValue = NSValue(CGPoint: CGPointMake(1.0, 1.0))
scaleAnimation.velocity = NSValue(CGPoint:CGPointMake(3.0, 3.0))
scaleAnimation.springBounciness = 18.0
self.layer.pop_addAnimation(scaleAnimation, forKey: "scaleAnimation")
}
}

创建 ButtonViewController

用于实现我们 GIF 图的效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import UIKit
class ButtonViewController: UIViewController {
var flatButton = FlatButton.button()//按钮
var errorLabel = UILabel()//错误标签
var activityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.Gray)//导航栏右侧Item
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
addButton()//添加按钮
addLabel()//添加标签
addActivityIndicatorView()//添加活动指示视图
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
errorLabel.layer.transform = CATransform3DMakeScale(0.5, 0.5, 1)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/**
添加按钮
*/
func addButton(){
flatButton.backgroundColor = UIColor(red: 52/255.0, green: 152/255.0, blue: 219/255.0, alpha: 1.0)
flatButton.setTitle("Log in", forState: UIControlState.Normal)
flatButton.setTranslatesAutoresizingMaskIntoConstraints(false)
flatButton.addTarget(self, action: "touchUpInside:", forControlEvents: UIControlEvents.TouchUpInside)
view.addSubview(flatButton)
//添加约束
self.view.addConstraint(NSLayoutConstraint(item: flatButton, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0.0))
self.view.addConstraint(NSLayoutConstraint(item: flatButton, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0.0))
}
/**
添加标签
*/
func addLabel(){
errorLabel.font = UIFont(name: "Avenir-Light", size: 18)
errorLabel.textColor = UIColor(red: 231/255.0, green: 76/255.0, blue: 60/255.0, alpha: 1.0)
errorLabel.setTranslatesAutoresizingMaskIntoConstraints(false)
errorLabel.text = "Just a serious login error."
errorLabel.textAlignment = NSTextAlignment.Center
view.insertSubview(errorLabel, belowSubview: flatButton)
//添加约束
self.view.addConstraint(NSLayoutConstraint(item: errorLabel, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: flatButton, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0.0))
self.view.addConstraint(NSLayoutConstraint(item: errorLabel, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: flatButton, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0.0))
errorLabel.layer.transform = CATransform3DMakeScale(0.5, 0.5, 1)
}
/**
添加活动指示图
*/
func addActivityIndicatorView(){
activityIndicatorView.hidesWhenStopped = true
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: activityIndicatorView)
}
/**
按钮点击时
:param: button 按钮
*/
func touchUpInside(button: FlatButton){
button.userInteractionEnabled = false
activityIndicatorView.startAnimating()
hiddenErrorLabel()
let delayTime = dispatch_time(DISPATCH_TIME_NOW,
Int64(1 * Double(NSEC_PER_SEC)))
dispatch_after(delayTime, dispatch_get_main_queue()) {
self.shakeFlatButton()
self.showErrorLabel()
self.activityIndicatorView.stopAnimating()
}
}
/**
摇晃按钮
*/
func shakeFlatButton(){
var shakeSpringAnimation = POPSpringAnimation(propertyNamed: kPOPLayerPositionX)
shakeSpringAnimation.velocity = NSNumber(float: 2000.0)
shakeSpringAnimation.springBounciness = 20.0
shakeSpringAnimation.completionBlock = {(animation, finished) in
self.flatButton.userInteractionEnabled = true
}
flatButton.layer.pop_addAnimation(shakeSpringAnimation, forKey: "shakeSpringAnimation")
}
/**
显示错误提示标签
*/
func showErrorLabel(){
//缩放
var scaleSpringAnimation = POPSpringAnimation(propertyNamed: kPOPLayerScaleXY)
scaleSpringAnimation.toValue = NSValue(CGPoint: CGPointMake(1, 1))
scaleSpringAnimation.velocity = NSValue(CGPoint: CGPointMake(3, 3))
scaleSpringAnimation.springBounciness = 20.0
errorLabel.layer.pop_addAnimation(scaleSpringAnimation, forKey: "scaleSpringAnimation")
//position Y
var positionSpringAnimation = POPSpringAnimation(propertyNamed: kPOPLayerPositionY)
positionSpringAnimation.toValue = NSNumber(float: Float(flatButton.layer.position.y + flatButton.intrinsicContentSize().height))
positionSpringAnimation.springBounciness = 20.0
errorLabel.layer.pop_addAnimation(positionSpringAnimation, forKey: "positionSpringAnimation")
}
/**
隐藏错误提示标签
*/
func hiddenErrorLabel(){
//缩放
var scaleSpringAnimation = POPSpringAnimation(propertyNamed: kPOPLayerScaleXY)
scaleSpringAnimation.toValue = NSValue(CGPoint: CGPointMake(0.5, 0.5))
scaleSpringAnimation.velocity = NSValue(CGPoint: CGPointMake(3, 3))
scaleSpringAnimation.springBounciness = 20.0
errorLabel.layer.pop_addAnimation(scaleSpringAnimation, forKey: "scaleSpringAnimation")
//position Y
var positionSpringAnimation = POPSpringAnimation(propertyNamed: kPOPLayerPositionY)
positionSpringAnimation.toValue = NSNumber(float: Float(flatButton.layer.position.y))
positionSpringAnimation.springBounciness = 20.0
errorLabel.layer.pop_addAnimation(positionSpringAnimation, forKey: "positionSpringAnimation")
}
}