2016-11-24 62 views
0

我試圖通過覆蓋CALayer實現「隱式動畫」。我閱讀了文檔,發現它很複雜。更重要的是,我找不到任何體面的代碼示例,或者網絡帖子來解釋它或使用任何Swift。子類化CALayer +隱式動畫w/Swift3

我已經實現了子類BandBaseCG試圖爲屬性param1提供隱式動畫,並覆蓋needsDisplay(forKey:)這與我的屬性,我返回true調用一次。

但是,這裏出錯了。我的理解是,我必須返回一個符合CAAction協議的對象,比如CABasicAnimation,這就是我所做的。但是,action(forKey:)defaultAction(forKey:)不會使用param1密鑰進行調用。

所以據我所知,在某些時候,我可以提供核心圖形的繪製draw(in ctx:)代碼來實現在迴應一些layer.param1 = 2實際隱含的動畫。但我不能達到這一點,因爲API根本不能按照我的預期工作。

這是我目前的執行:

import Foundation 
import QuartzCore 

class BandBaseCG: CALayer { 

    @NSManaged var param1: Float 

    override init(layer: Any) { 

     super.init(layer: layer) 

    } 

    override init() { 
     super.init() 

    } 

    required init?(coder aDecoder: NSCoder) { 
     fatalError("init(coder:) has not been implemented") 
    } 


    override func action(forKey event: String) -> CAAction? { 

     print(event) 

     if event == "param1" { 

     let ba = CABasicAnimation(keyPath: event) 
     ba.duration = 2 
     ba.fromValue = (presentation()! as BandBaseCG).param1 
     ba.toValue = 2 

     return ba 
     } 

     return super.action(forKey: event) 
    } 


    override func draw(in ctx: CGContext) { 
     print("draw") 
    } 


    override class func defaultAction(forKey event: String) -> CAAction?  { 

     if event == "param1" { 

     let ba = CABasicAnimation(keyPath: event) 
     ba.duration = 2 
     ba.fromValue = 0 
     ba.toValue = 2 

     return ba 
     } 

     return super.defaultAction(forKey: event) 
    } 

    override class func needsDisplay(forKey key: String) -> Bool { 

     print(key) 

     if key == "param1" { 
     return true 
     } 

     return super.needsDisplay(forKey: key) 
    } 

    override func display() { 
     print("param value: \(param1)") 
    } 

} 

回答

1

下面是一個完整的工作示例(從我的書):

class MyView : UIView { // exists purely to host MyLayer 
    override class var layerClass : AnyClass { 
     return MyLayer.self 
    } 
    override func draw(_ rect: CGRect) {} // so that layer will draw itself 
} 
class MyLayer : CALayer { 
    @NSManaged var thickness : CGFloat 
    override class func needsDisplay(forKey key: String) -> Bool { 
     if key == #keyPath(thickness) { 
      return true 
     } 
     return super.needsDisplay(forKey:key) 
    } 
    override func draw(in con: CGContext) { 
     let r = self.bounds.insetBy(dx:20, dy:20) 
     con.setFillColor(UIColor.red.cgColor) 
     con.fill(r) 
     con.setLineWidth(self.thickness) 
     con.stroke(r) 
    } 
    override func action(forKey key: String) -> CAAction? { 
     if key == #keyPath(thickness) { 
      let ba = CABasicAnimation(keyPath: key) 
      ba.fromValue = self.presentation()!.value(forKey:key) 
      return ba 
     } 
     return super.action(forKey:key) 
    } 
} 

你會發現,如果你把一個MyView的到你的應用程序,你可以說

let lay = v.layer as! MyLayer 
lay.thickness = 10 // or whatever 

而且它將動畫化邊界厚度的變化。 「

+0

」更重要的是,我找不到任何體面的代碼示例,或者使用任何Swift進行解釋的網絡帖子。「好吧,我認爲這是一個「體面」的代碼示例。至於說明,你顯然沒有看過我的書,那不是你的錯。但它確實存在,我認爲它解釋了代碼的所有部分(當然,只是我的意見)。 – matt

+0

我不認爲這是公平的。我花了幾個小時在網上搜索,發現這個問題很少。至於你的書,我很樂意瞭解它,並且在將來一定會諮詢它。感謝您的答覆。 –

+0

放鬆。我說這不是你的錯!沒有傷害沒有犯規。我給了你代碼,你會發現它的工作原理(並且有一個可下載的完整項目)。我們在這裏是同一個團隊。 – matt