UIView本身對于基本動(dòng)畫和關(guān)鍵幀動(dòng)畫军俊、轉(zhuǎn)場動(dòng)畫都有相應(yīng)的封裝阔涉,在對動(dòng)畫細(xì)節(jié)沒有特殊要求的情況下使用起來也要簡單的多晨逝《昴可以說在日常開發(fā)中90%以上的情況使用UIView的動(dòng)畫封裝方法都可以搞定.
常見動(dòng)畫設(shè)置方法
//標(biāo)記動(dòng)畫的開始
open class func beginAnimations(_ animationID: String?, context: UnsafeMutableRawPointer?)
//提交動(dòng)畫
open class func commitAnimations()
//設(shè)置動(dòng)畫代理對象,當(dāng)動(dòng)畫開始或者結(jié)束時(shí)會(huì)發(fā)消息給代理對象
open class func setAnimationDelegate(_ delegate: Any?)
//當(dāng)動(dòng)畫即將開始時(shí)咏花,執(zhí)行delegate對象的selector趴生,并且把beginAnimations:context:中傳入的參數(shù)傳進(jìn)selector
open class func setAnimationWillStart(_ selector: Selector?)
//當(dāng)動(dòng)畫結(jié)束時(shí)阀趴,執(zhí)行delegate對象的selector昏翰,并且把beginAnimations:context:中傳入的參數(shù)傳進(jìn)selector
open class func setAnimationDidStop(_ selector: Selector?)
//動(dòng)畫的持續(xù)時(shí)間,秒為單位
open class func setAnimationDuration(_ duration: TimeInterval)
//動(dòng)畫延遲delay秒后再開始
open class func setAnimationDelay(_ delay: TimeInterval)
//動(dòng)畫的開始時(shí)間刘急,默認(rèn)為now
open class func setAnimationStart(_ startDate: Date)
//動(dòng)畫的時(shí)間變化類型
open class func setAnimationCurve(_ curve: UIView.AnimationCurve)
//動(dòng)畫的重復(fù)次數(shù)
open class func setAnimationRepeatCount(_ repeatCount: Float)
//如果設(shè)置為YES,代表動(dòng)畫每次重復(fù)執(zhí)行的效果會(huì)跟上一次相反
open class func setAnimationRepeatAutoreverses(_ repeatAutoreverses: Bool)
//設(shè)置視圖view的過渡效果, transition指定過渡類型, cache設(shè)置YES代表使用視圖緩存棚菊,性能較好.
open class func setAnimationTransition(_ transition: UIView.AnimationTransition, for view: UIView, cache: Bool)
//是否允許動(dòng)畫
open class func setAnimationsEnabled(_ enabled: Bool)
可動(dòng)畫屬性
-
bounds
: Animate this property to reposition the view’s content within the view’s frame. -
frame
: Animate this property to move and/or scale the view. -
center
: Animate this property when you want to move the view to a new location on screen. -
backgroundColor
: Change this property of a view to have UIKit gradually change the tint of the background color over time. -
alpha
: Change this property to create fade-in and fade-out effects. -
transform
: Modify this property within an animation block to animate the rotation, scale, and/or position of a view.
動(dòng)畫的方式
1、使用必包方式
UIView.animate(withDuration: 1, animations: {
// animate code
}, completion: { finished in
// animation finished
})
2叔汁、使用begin和commit方式
UIView.beginAnimations("animate", context: nil)
UIView.setAnimationDuration(0.5)
animationView.backgroundColor = UIColor.cyan
UIView.commitAnimations()
動(dòng)畫的類型
基本動(dòng)畫
使用UIView進(jìn)行動(dòng)畫非常簡單统求,iOS 提供了很方便的函數(shù)
extension UIView {
@available(iOS 4.0, *)
open class func animate(withDuration duration: TimeInterval,
delay: TimeInterval,
options: UIViewAnimationOptions = [],
animations: @escaping () -> Swift.Void,
completion: ((Bool) -> Swift.Void)? = nil)
@available(iOS 4.0, *)
open class func animate(withDuration duration: TimeInterval,
animations: @escaping () -> Swift.Void,
completion: ((Bool) -> Swift.Void)? = nil) // delay = 0.0, options = 0
@available(iOS 4.0, *)
open class func animate(withDuration duration: TimeInterval,
animations: @escaping () -> Swift.Void) // delay = 0.0, options = 0, completion = NULL
}
duration:動(dòng)畫的持續(xù)時(shí)間
delay:延遲動(dòng)畫時(shí)間
options:動(dòng)畫進(jìn)行的方式,不同的選項(xiàng)直接可以通過“與”操作進(jìn)行合并据块,同時(shí)使用码邻,可以分為兩類:
控制速度:
//動(dòng)畫先緩慢,然后逐漸加速另假,再變慢
public static var curveEaseInOut: UIViewAnimationOptions { get } //default
//
public static var curveEaseIn: UIViewAnimationOptions { get }
//動(dòng)畫開始快像屋,后面慢
public static var curveEaseOut: UIViewAnimationOptions { get }
//動(dòng)畫勻速執(zhí)行
public static var curveLinear: UIViewAnimationOptions { get }
如圖所示
控制過程:
public static var allowUserInteraction: UIViewAnimationOptions { get } // turn on user interaction while animating
public static var beginFromCurrentState: UIViewAnimationOptions { get } // start all views from current value, not initial value
public static var `repeat`: UIViewAnimationOptions { get } // repeat animation indefinitely
public static var autoreverse: UIViewAnimationOptions { get } // if repeat, run animation back and forth
animations:動(dòng)畫閉包,在 animations中對 UIView 的屬性進(jìn)行動(dòng)畫
completion:動(dòng)畫完成閉包
移動(dòng)圖片
實(shí)現(xiàn)一個(gè)簡單的需求边篮,點(diǎn)擊屏幕移動(dòng)圖片
閉包方式
class UIViewAnimationController: UIViewController {
lazy var imageView: UIImageView = {
let imageV = UIImageView(image: UIImage(named: "man"))
return imageV
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white
view.addSubview(imageView)
imageView.center = view.center
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first!
let location = touch.location(in: view)
// 根據(jù)需求選擇對應(yīng)的方法設(shè)置對應(yīng)的屬性
UIView.animate(withDuration: 0.5) {
self.imageView.center = location
}
}
}
提交動(dòng)畫方式
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first!
let location = touch.location(in: view)
// 根據(jù)需求設(shè)置相應(yīng)屬性
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(0.5)
self.imageView.center = location
UIView.commitAnimations()
}
效果如下
關(guān)鍵幀動(dòng)畫
有些時(shí)候我們需要自己設(shè)定若干關(guān)鍵幀己莺,實(shí)現(xiàn)更復(fù)雜的動(dòng)畫效果,這時(shí)候就需要關(guān)鍵幀動(dòng)畫的支持了
extension UIView {
@available(iOS 7.0, *)
open class func animateKeyframes(withDuration duration: TimeInterval,
delay: TimeInterval,
options: UIViewKeyframeAnimationOptions = [],
animations: @escaping () -> Swift.Void,
completion: ((Bool) -> Swift.Void)? = nil)
// start time and duration are values between 0.0 and 1.0 specifying time and duration
// relative to the overall time of the keyframe animation
@available(iOS 7.0, *)
open class func addKeyframe(withRelativeStartTime frameStartTime: Double,
relativeDuration frameDuration: Double,
animations: @escaping () -> Swift.Void)
}
同樣是一張圖片顯示在界面上,點(diǎn)擊界面觸發(fā)關(guān)鍵幀動(dòng)畫戈轿。實(shí)現(xiàn)如下凌受,會(huì)按照設(shè)置的時(shí)間進(jìn)行動(dòng)畫
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
UIView.animateKeyframes(withDuration: 5.0, delay: 0.0, options: .calculationModeLinear, animations: {
UIView.addKeyframe(withRelativeStartTime: 0.0, //相對于5秒所開始的時(shí)間(第0秒開始動(dòng)畫)
relativeDuration: 0.5, //相對于5秒所持續(xù)時(shí)間(也就是5.0*0.5=2.5秒)
animations: {
self.imageView.center = CGPoint(x: 100, y: 220)
})
UIView.addKeyframe(withRelativeStartTime: 0.5, //相對于5秒所持續(xù)時(shí)間(也就是5.0*0.5=2.5秒)
relativeDuration: 0.25, //相對于5秒所持續(xù)時(shí)間(持續(xù)5.0*0.25=1.25秒)
animations: {
self.imageView.center = CGPoint(x: 60, y: 300)
})
UIView.addKeyframe(withRelativeStartTime: 0.75, //相對于5秒所開始的時(shí)間(從0.75*5.0秒開始)
relativeDuration: 0.25, //相對于5秒所持續(xù)時(shí)間(持續(xù)5.0*0.25=1.25秒)
animations: {
self.imageView.center = CGPoint(x: 120, y: 440)
})
}, completion: { finished in
print("animation finished")
})
}
過渡動(dòng)畫
過渡動(dòng)畫API
@available(iOS 4.0, *)
open class func transition(with view: UIView,
duration: TimeInterval,
options: UIViewAnimationOptions = [],
animations: (() -> Swift.Void)?,
completion: ((Bool) -> Swift.Void)? = nil)
// toView added to fromView.superview, fromView removed from its superview
@available(iOS 4.0, *)
open class func transition(from fromView: UIView,
to toView: UIView,
duration: TimeInterval,
options: UIViewAnimationOptions = [],
completion: ((Bool) -> Swift.Void)? = nil)
轉(zhuǎn)場類型(僅適用于轉(zhuǎn)場動(dòng)畫設(shè)置,可以從中選擇一個(gè)進(jìn)行設(shè)置思杯,基本動(dòng)畫胜蛉、關(guān)鍵幀動(dòng)畫不需要設(shè)置)
UIViewAnimationOptionTransitionNone:沒有轉(zhuǎn)場動(dòng)畫效果。
UIViewAnimationOptionTransitionFlipFromLeft :從左側(cè)翻轉(zhuǎn)效果色乾。
UIViewAnimationOptionTransitionFlipFromRight:從右側(cè)翻轉(zhuǎn)效果誊册。
UIViewAnimationOptionTransitionCurlUp:向后翻頁的動(dòng)畫過渡效果。
UIViewAnimationOptionTransitionCurlDown :向前翻頁的動(dòng)畫過渡效果杈湾。
UIViewAnimationOptionTransitionCrossDissolve:舊視圖溶解消失顯示下一個(gè)新視圖的效果解虱。
UIViewAnimationOptionTransitionFlipFromTop :從上方翻轉(zhuǎn)效果。
UIViewAnimationOptionTransitionFlipFromBottom:從底部翻轉(zhuǎn)效果漆撞。
單視圖的轉(zhuǎn)場動(dòng)畫
點(diǎn)擊屏幕切換頭像
lazy var imageView: UIImageView = {
let imageV = UIImageView(image: UIImage(named: "man"))
return imageV
}()
var images = ["1","2","3","4","man"]
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white
view.addSubview(imageView)
imageView.center = view.center
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
UIView.transition(with: imageView, duration: 1.0, options: .transitionCrossDissolve, animations: {
let random = arc4random_uniform(UInt32(self.images.count))
self.imageView.image = UIImage(named: self.images[Int(random)])
}, completion: nil)
}
效果如下
雙視圖轉(zhuǎn)場動(dòng)畫
簡單實(shí)現(xiàn)視圖之間的切換
class ViewTransitionController: UIViewController {
lazy var subView1: UIView = {
let view = UIView(frame: self.view.bounds)
view.backgroundColor = UIColor.red
return view
}()
lazy var subView2: UIView = {
let view = UIView(frame: self.view.bounds)
view.backgroundColor = UIColor.blue
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(subView1)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
var toView: UIView?
var fromView: UIView?
if subView1.superview == nil {
toView = subView1
fromView = subView2
} else {
toView = subView2
fromView = subView1
}
UIView.transition(from: fromView!, to: toView!, duration: 1.0, options: .transitionFlipFromLeft) { finished in
print("subView1:\(self.subView1.superview) subView2: \(self.subView2.superview)")
}
}
}
效果如下
彈性動(dòng)畫
@available(iOS 7.0, *)
open class func animate(withDuration duration: TimeInterval,
delay: TimeInterval,
usingSpringWithDamping dampingRatio: CGFloat,
initialSpringVelocity velocity: CGFloat,
options: UIView.AnimationOptions = [],
animations: @escaping () -> Void,
completion: ((Bool) -> Void)? = nil)
springDamping
彈性阻尼殴泰,取值范圍時(shí) 0 到 1于宙,越接近 0 ,動(dòng)畫的彈性效果就越明顯悍汛;如果設(shè)置為 1捞魁,則動(dòng)畫不會(huì)有彈性效果
initialSpringVelocity
數(shù)值越小,動(dòng)力越小离咐,彈簧的拉伸幅度就越小谱俭。反之相反。比如:總共的動(dòng)畫運(yùn)行距離是200 pt宵蛀,你希望每秒 100pt 時(shí)昆著,值為 0.5;
在 initialSpringVelocity 為 0 术陶,damping 分別為 0.4凑懂,0.6,0.8 的情況下效果如圖梧宫,可見阻尼越小接谨,彈簧效果越明顯