iOS中UIView的動(dòng)畫

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 }

如圖所示

4010043-91de89b45c0b810f.gif

控制過程:

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()
    }

效果如下

move.2018-11-16 18_53_21.gif

關(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)
    }

效果如下

tran.2018-11-16 19_19_17.gif

雙視圖轉(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)")
        }
    }
}

效果如下

transition.2018-11-17 11_00_02.gif

彈性動(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 的情況下效果如圖梧宫,可見阻尼越小接谨,彈簧效果越明顯

2018-11-17 11-54-56.2018-11-17 11_55_12.gif
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市塘匣,隨后出現(xiàn)的幾起案子脓豪,更是在濱河造成了極大的恐慌,老刑警劉巖忌卤,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件扫夜,死亡現(xiàn)場離奇詭異,居然都是意外死亡埠巨,警方通過查閱死者的電腦和手機(jī)历谍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來辣垒,“玉大人望侈,你說我怎么就攤上這事⊙埃” “怎么了脱衙?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長例驹。 經(jīng)常有香客問我捐韩,道長,這世上最難降的妖魔是什么鹃锈? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任荤胁,我火速辦了婚禮,結(jié)果婚禮上屎债,老公的妹妹穿的比我還像新娘仅政。我一直安慰自己垢油,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布圆丹。 她就那樣靜靜地躺著滩愁,像睡著了一般巡验。 火紅的嫁衣襯著肌膚如雪括堤。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天缠黍,我揣著相機(jī)與錄音倦微,去河邊找鬼妻味。 笑死,一個(gè)胖子當(dāng)著我的面吹牛璃诀,可吹牛的內(nèi)容都是我干的弧可。 我是一名探鬼主播蔑匣,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼劣欢,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了裁良?” 一聲冷哼從身側(cè)響起凿将,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎价脾,沒想到半個(gè)月后牧抵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡侨把,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年犀变,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片秋柄。...
    茶點(diǎn)故事閱讀 38,626評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡获枝,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出骇笔,到底是詐尸還是另有隱情省店,我是刑警寧澤,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布笨触,位于F島的核電站懦傍,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏芦劣。R本人自食惡果不足惜粗俱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望虚吟。 院中可真熱鬧寸认,春花似錦娱俺、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至烛愧,卻和暖如春油宜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背怜姿。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工慎冤, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人沧卢。 一個(gè)月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓蚁堤,卻偏偏與公主長得像,于是被迫代替她去往敵國和親但狭。 傳聞我的和親對象是個(gè)殘疾皇子披诗,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,494評論 2 348

推薦閱讀更多精彩內(nèi)容