iOS核心動畫高級技巧(筆記)——(六)隱式動畫

動畫是Core Animation庫一個非常顯著的特性。這一章我們來看看它是怎么做到的经柴。具體來說丈探,我們先來討論框架自動完成的隱式動畫(除非你明確禁用了這個功能)欺殿。

事務

  • 事務是Core Animation用來包含一系列屬性動畫集合的機制搂擦,任何用指定事務去改變可以做動畫的圖層屬性都不會立刻發(fā)生變化稳诚,而是當事務一旦提交的時候開始用一個動畫過渡到新值。
    事務是通過CATransaction類來做管理瀑踢,可以用+begin+commit分別來入棧或者出棧才避。CATransaction+begin+commit方法與UIView+beginAnimations:context:+commitAnimations方法類似橱夭。
    任何可以做動畫的圖層屬性都會被添加到棧頂?shù)氖聞眨憧梢酝ㄟ^+setAnimationDuration:方法設置當前事務的動畫時間桑逝,或者通過+animationDuration方法來獲取值(默認0.25秒)棘劣。

完成塊

  • 基于UIView的block的動畫允許你在動畫結(jié)束的時候提供一個完成的動作。CATranscation接口提供的+setCompletionBlock:方法也有同樣的功能楞遏。來看一個例子茬暇,首先創(chuàng)建一個藍色的方塊,然后添加一個按鈕寡喝,隨機改變它的顏色糙俗,再添加一個完成之后的block,用來在每次顏色變化結(jié)束之后切換到另一個旋轉(zhuǎn)45度的動畫预鬓。點擊按鈕巧骚,你會發(fā)現(xiàn)圖層的顏色平滑過渡到一個新值,而不是跳變格二。并且旋轉(zhuǎn)動畫要比顏色漸變快得多劈彪,這是因為完成塊是在顏色漸變的事務提交并出棧之后才被執(zhí)行,于是顶猜,用默認的事務做變換沧奴,默認的時間也就變成了0.25秒。
    var colorLayer = CALayer()
    @IBOutlet weak var layerView: UIView!
    @IBAction func changeColor(sender: UIButton) {
    CATransaction.begin()
    CATransaction.setAnimationDuration(2.0)

      let red = CGFloat(arc4random()) / CGFloat(INT_MAX)
      let green = CGFloat(arc4random()) / CGFloat(INT_MAX)
      let blue = CGFloat(arc4random()) / CGFloat(INT_MAX)
      self.colorLayer.backgroundColor = UIColor(red: red, green: green, blue: blue, alpha: 1.0).CGColor
      
      CATransaction.setCompletionBlock({
          var transform = self.colorLayer.affineTransform()
          transform = CGAffineTransformRotate(transform, CGFloat(M_PI_2) / 2.0)
          self.colorLayer.setAffineTransform(transform)
          
      })
      
      CATransaction.commit()
    }
    override func viewDidLoad() {
      self.colorLayer.frame = CGRectMake(50, 50, 100, 100)
      self.colorLayer.backgroundColor = UIColor.blueColor().CGColor
      self.layerView.layer.addSublayer(self.colorLayer)
    }
    
gif

圖層行為

  • 對上一個例子做一點修改长窄,移除colorLayer滔吠,并且直接設置layerView關(guān)聯(lián)圖層的背景色纲菌,現(xiàn)在是直接對UIView關(guān)聯(lián)的圖層做動畫而不是一個單獨的圖層。運行程序屠凶,會發(fā)現(xiàn)當按下按鈕驰后,圖層顏色瞬間切換到新的值,而不是之前平滑過渡的動畫矗愧。這是因為隱式動畫被UIVew關(guān)聯(lián)圖層給禁用了灶芝。
    UIView關(guān)聯(lián)的圖層禁用了隱式動畫,對這種圖層做動畫的唯一辦法就是使用UIView的動畫函數(shù)(而不是依賴CATransaction)唉韭,或者繼承UIView夜涕,并覆蓋-actionForLayer:forKey:方法,或者直接創(chuàng)建一個顯式動畫(具體細節(jié)見第七章)属愤。對于單獨存在的圖層女器,我們可以通過實現(xiàn)圖層的-actionForLayer:forKey:委托方法,或者提供一個actions字典來控制隱式動畫住诸。
    CATransacition有個方法叫做+setDisableActions:驾胆,可以用來對所有屬性打開或者關(guān)閉隱式動畫。
    我們來對顏色漸變的例子使用一個不同的行為贱呐,通過給colorLayer設置一個自定義的actions字典丧诺。 行為通常是一個被Core Animation隱式調(diào)用的顯式動畫對象。這里我們使用的是一個實現(xiàn)了CATransaction的實例奄薇,叫做推進過渡驳阎。第七章中將會詳細解釋過渡,不過對于現(xiàn)在馁蒂,知道CATransition響應CAAction協(xié)議呵晚,并且可以當做一個圖層行為就足夠了。結(jié)果是不論在什么時候改變背景顏色沫屡,新的色塊都是從左側(cè)滑入饵隙,而不是默認的漸變效果。
    @IBOutlet weak var layerView: UIView!
    var colorLayer = CALayer()

    @IBAction func changeColor(sender: UIButton) {
      CATransaction.begin()
      CATransaction.setAnimationDuration(2)
      
      let red = CGFloat(arc4random() / UINT32_MAX)
      let green = CGFloat(arc4random()) / CGFloat(INT_MAX)
      let blue = CGFloat(arc4random()) / CGFloat(INT_MAX)
      self.colorLayer.backgroundColor = UIColor(red: red, green: green, blue: blue, alpha: 1.0).CGColor
      
      CATransaction.commit()
    }
    override func viewDidLoad() {
      self.colorLayer.frame = CGRectMake(50, 50, 100, 100)
      self.colorLayer.backgroundColor = UIColor.blueColor().CGColor
      self.layerView.layer.addSublayer(self.colorLayer)
      
      let transition = CATransition()
      transition.type = kCATransitionPush
      transition.subtype = kCATransitionFromLeft
      self.colorLayer.actions = ["backgroundColor" : transition] 
    }
    
推進過渡

呈現(xiàn)與模型

  • 在iOS中谁鳍,屏幕每秒鐘重繪60次癞季。如果動畫時長比60分之一秒要長,Core Animation就需要在設置一次新值和新值生效之間倘潜,對屏幕上的圖層進行重新組織绷柒。這意味著CALayer除了“真實”值(就是你設置的值)之外,必須要知道當前顯示在屏幕上的屬性值的記錄涮因。
    每個圖層屬性的顯示值都被存儲在一個叫做呈現(xiàn)圖層的獨立圖層當中废睦,他可以通過-presentationLayer方法來訪問。這個呈現(xiàn)圖層實際上是模型圖層的復制养泡,但是它的屬性值代表了在任何指定時刻當前外觀效果嗜湃。換句話說奈应,你可以通過呈現(xiàn)圖層的值來獲取當前屏幕上真正顯示出來的值。
    一個移動的圖層是如何通過數(shù)據(jù)模型呈現(xiàn)的

    大多數(shù)情況下购披,你不需要直接訪問呈現(xiàn)圖層杖挣,你可以通過和模型圖層的交互,來讓Core Animation更新顯示刚陡。兩種情況下呈現(xiàn)圖層會變得很有用惩妇,一個是同步動畫,一個是處理用戶交互筐乳。
    1.如果你在實現(xiàn)一個基于定時器的動畫(見第10章“基于定時器的動畫”)歌殃,而不僅僅是基于事務的動畫,這個時候準確地知道在某一時刻圖層顯示在什么位置就會對正確擺放圖層很有用了蝙云。
    2.如果你想讓你做動畫的圖層響應用戶輸入氓皱,你可以使用-hitTest:方法來判斷指定圖層是否被觸摸,這時候?qū)Τ尸F(xiàn)圖層而不是模型圖層調(diào)用-hitTest:會顯得更有意義勃刨,因為呈現(xiàn)圖層代表了用戶當前看到的圖層位置波材,而不是當前動畫結(jié)束之后的位置
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    let point = (touches as NSSet).anyObject()?.locationInView(self.view)
    if ((self.colorLayer.presentationLayer()!.hitTest(point!)) != nil) {
    }
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末身隐,一起剝皮案震驚了整個濱河市各聘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌抡医,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件早敬,死亡現(xiàn)場離奇詭異忌傻,居然都是意外死亡,警方通過查閱死者的電腦和手機搞监,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進店門水孩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人琐驴,你說我怎么就攤上這事俘种。” “怎么了绝淡?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵宙刘,是天一觀的道長。 經(jīng)常有香客問我牢酵,道長悬包,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任馍乙,我火速辦了婚禮布近,結(jié)果婚禮上垫释,老公的妹妹穿的比我還像新娘。我一直安慰自己撑瞧,他們只是感情好棵譬,可當我...
    茶點故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著预伺,像睡著了一般订咸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上扭屁,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天算谈,我揣著相機與錄音,去河邊找鬼料滥。 笑死然眼,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的葵腹。 我是一名探鬼主播高每,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼践宴!你這毒婦竟也來了鲸匿?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤阻肩,失蹤者是張志新(化名)和其女友劉穎带欢,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體烤惊,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡乔煞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了柒室。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片渡贾。...
    茶點故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖雄右,靈堂內(nèi)的尸體忽然破棺而出空骚,到底是詐尸還是另有隱情,我是刑警寧澤擂仍,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布囤屹,位于F島的核電站,受9級特大地震影響防楷,放射性物質(zhì)發(fā)生泄漏牺丙。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望冲簿。 院中可真熱鬧粟判,春花似錦、人聲如沸峦剔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽吝沫。三九已至呻澜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間惨险,已是汗流浹背羹幸。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留辫愉,地道東北人栅受。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像恭朗,于是被迫代替她去往敵國和親屏镊。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,697評論 2 351

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